Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http/./../../../../netwerk/protocol/http/nsHttpChannel.cpp
Warning:line 12597, column 12
Value stored to 'rv' during its initialization 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/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-10-17-231001-351276-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/LoadInfo.h"
32#include "mozilla/NullPrincipal.h"
33#include "mozilla/PerfStats.h"
34#include "mozilla/ProfilerDumpOrCrash.h"
35#include "mozilla/ProfilerLabels.h"
36#include "mozilla/ScopeExit.h"
37#include "mozilla/Services.h"
38#include "mozilla/Sprintf.h"
39#include "mozilla/StaticPrefs_dom.h"
40#include "mozilla/StaticPrefs_network.h"
41#include "mozilla/StaticPrefs_privacy.h"
42#include "mozilla/StaticPrefs_security.h"
43#include "mozilla/StoragePrincipalHelper.h"
44#include "mozilla/Telemetry.h"
45#include "mozilla/TimeStamp.h"
46#include "mozilla/ToString.h"
47#include "mozilla/dom/ClientInfo.h"
48#include "mozilla/dom/Document.h"
49#include "mozilla/dom/NavigatorLogin.h"
50#include "mozilla/dom/PerformanceStorage.h"
51#include "mozilla/dom/PolicyContainer.h"
52#include "mozilla/dom/ReferrerInfo.h"
53#include "mozilla/dom/SecFetch.h"
54#include "mozilla/dom/ServiceWorkerUtils.h"
55#include "mozilla/dom/WindowGlobalParent.h"
56#include "mozilla/dom/nsCSPContext.h"
57#include "mozilla/dom/nsHTTPSOnlyStreamListener.h"
58#include "mozilla/dom/nsHTTPSOnlyUtils.h"
59#include "mozilla/extensions/StreamFilterParent.h"
60#include "mozilla/glean/AntitrackingMetrics.h"
61#include "mozilla/glean/DomSecurityMetrics.h"
62#include "mozilla/glean/NetwerkMetrics.h"
63#include "mozilla/glean/NetwerkProtocolHttpMetrics.h"
64#include "mozilla/net/AsyncUrlChannelClassifier.h"
65#include "mozilla/net/CaptivePortalService.h"
66#include "mozilla/net/ChannelClassifierUtils.h"
67#include "mozilla/net/CookieJarSettings.h"
68#include "mozilla/net/CookieServiceParent.h"
69#include "mozilla/net/NeckoChannelParams.h"
70#include "mozilla/net/NoVarySearchUtils.h"
71#include "mozilla/net/OpaqueResponseUtils.h"
72#include "mozilla/net/SFVService.h"
73#include "mozilla/net/SocketProcessParent.h"
74#include "mozilla/net/TRRService.h"
75#include "mozilla/net/URLPatternGlue.h"
76#include "mozilla/net/urlpattern_glue.h"
77#include "netCore.h"
78#include "nsCOMPtr.h"
79#include "nsCORSListenerProxy.h"
80#include "nsCRT.h"
81#include "nsChannelClassifier.h"
82#include "nsCharSeparatedTokenizer.h"
83#include "nsComponentManagerUtils.h"
84#include "nsContentSecurityManager.h"
85#include "nsContentSecurityUtils.h"
86#include "nsContentUtils.h"
87#include "nsDNSPrefetch.h"
88#include "nsError.h"
89#include "nsEscape.h"
90#include "nsHttp.h"
91#include "nsHttpChannelAuthProvider.h"
92#include "nsHttpConnectionMgr.h"
93#include "nsHttpHandler.h"
94#include "nsHttpTransaction.h"
95#include "nsICacheEntry.h"
96#include "nsICacheStorage.h"
97#include "nsICacheStorageService.h"
98#include "nsICancelable.h"
99#include "nsIClassOfService.h"
100#include "nsICompressConvStats.h"
101#include "nsIConsoleService.h"
102#include "nsICookieNotification.h"
103#include "nsICryptoHash.h"
104#include "nsIDNSRecord.h"
105#include "nsIEffectiveTLDService.h"
106#include "nsIHttpChannelInternal.h"
107#include "nsIHttpHeaderVisitor.h"
108#include "nsINetworkErrorLogging.h"
109#include "nsINetworkInterceptController.h"
110#include "nsINetworkLinkService.h"
111#include "nsIOService.h"
112#include "nsIPrincipal.h"
113#include "nsIPrompt.h"
114#include "nsIProtocolProxyService2.h"
115#include "nsIRedirectResultListener.h"
116#include "nsIScriptError.h"
117#include "nsIScriptSecurityManager.h"
118#include "nsISeekableStream.h"
119#include "nsISiteIntegrityService.h"
120#include "nsISiteSecurityService.h"
121#include "nsISocketProvider.h"
122#include "nsISocketTransport.h"
123#include "nsIStreamConverter.h"
124#include "nsIStreamConverterService.h"
125#include "nsIStreamListenerTee.h"
126#include "nsIStreamTransportService.h"
127#include "nsIStringBundle.h"
128#include "nsISystemInfo.h"
129#include "nsITransportSecurityInfo.h"
130#include "nsIURIMutator.h"
131#include "nsIURLQueryStringStripper.h"
132#include "nsIWebProgressListener.h"
133#include "nsIWebTransport.h"
134#include "nsInputStreamPump.h"
135#include "nsMimeTypes.h"
136#include "nsMixedContentBlocker.h"
137#include "nsNetCID.h"
138#include "nsNetUtil.h"
139#include "nsPrintfCString.h"
140#include "nsQueryObject.h"
141#include "nsStreamUtils.h"
142#include "nsString.h"
143#include "nsStringStream.h"
144#include "nsThreadUtils.h"
145#include "nsURLHelper.h"
146#include "nsUnknownDecoder.h"
147#include "prnetdb.h"
148#include "sslt.h"
149#ifdef XP_WIN
150# include "HttpWinUtils.h"
151#endif
152#ifdef XP_MACOSX
153# include "MicrosoftEntraSSOUtils.h"
154#endif
155#ifdef FUZZING
156# include "mozilla/StaticPrefs_fuzzing.h"
157#endif
158
159#include "mozilla/dom/ReportDeliver.h"
160#include "mozilla/dom/ReportingHeader.h"
161
162namespace mozilla {
163
164using namespace dom;
165
166namespace net {
167
168namespace {
169
170// True if the local cache should be bypassed when processing a request.
171#define BYPASS_LOCAL_CACHE(loadFlags, isPreferCacheLoadOverBypass)((loadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((loadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (isPreferCacheLoadOverBypass)))
\
172 ((loadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | \
173 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE) && \
174 !(((loadFlags) & nsIRequest::LOAD_FROM_CACHE) && \
175 (isPreferCacheLoadOverBypass)))
176
177#define RECOVER_FROM_CACHE_FILE_ERROR(result)((result) == NS_ERROR_FILE_NOT_FOUND || (result) == NS_ERROR_FILE_CORRUPTED
|| (result) == NS_ERROR_OUT_OF_MEMORY)
\
178 ((result) == NS_ERROR_FILE_NOT_FOUND || \
179 (result) == NS_ERROR_FILE_CORRUPTED || (result) == NS_ERROR_OUT_OF_MEMORY)
180
181static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID)const nsCID kStreamListenerTeeCID = { 0x831f8f13, 0x7aa8, 0x485f
, {0xb0, 0x2e, 0x77, 0xc8, 0x81, 0xcc, 0x57, 0x73}}
;
182
183enum ChannelDisposition {
184 kHttpCanceled = 0,
185 kHttpDisk = 1,
186 kHttpNetOK = 2,
187 kHttpNetEarlyFail = 3,
188 kHttpNetLateFail = 4,
189 kHttpsCanceled = 8,
190 kHttpsDisk = 9,
191 kHttpsNetOK = 10,
192 kHttpsNetEarlyFail = 11,
193 kHttpsNetLateFail = 12
194};
195
196static nsLiteralCString CacheDispositionToTelemetryLabel(
197 nsICacheInfoChannel::CacheDisposition hitOrMiss) {
198 switch (hitOrMiss) {
199 case nsICacheInfoChannel::kCacheUnresolved:
200 return "Unresolved"_ns;
201 case nsICacheInfoChannel::kCacheHit:
202 return "Hit"_ns;
203 case nsICacheInfoChannel::kCacheHitViaReval:
204 return "HitViaReval"_ns;
205 case nsICacheInfoChannel::kCacheMissedViaReval:
206 return "MissedViaReval"_ns;
207 case nsICacheInfoChannel::kCacheMissed:
208 return "Missed"_ns;
209 case nsICacheInfoChannel::kCacheUnknown:
210 return "Unknown"_ns;
211 default:
212 return "Invalid"_ns;
213 }
214}
215
216void AccumulateCacheHitTelemetry(
217 nsICacheInfoChannel::CacheDisposition hitOrMiss, nsIChannel* aChannel) {
218 nsCString key("UNKNOWN");
219
220 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
221
222 nsAutoCString contentType;
223 if (NS_SUCCEEDED(aChannel->GetContentType(contentType))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aChannel->GetContentType
(contentType))), 1)))
) {
224 if (nsContentUtils::IsJavascriptMIMEType(
225 NS_ConvertUTF8toUTF16(contentType))) {
226 key.AssignLiteral("JAVASCRIPT");
227 } else if (StringBeginsWith(contentType, "text/css"_ns) ||
228 (loadInfo && loadInfo->GetExternalContentPolicyType() ==
229 ExtContentPolicy::TYPE_STYLESHEET)) {
230 key.AssignLiteral("STYLESHEET");
231 } else if (StringBeginsWith(contentType, "application/wasm"_ns)) {
232 key.AssignLiteral("WASM");
233 } else if (StringBeginsWith(contentType, "image/"_ns)) {
234 key.AssignLiteral("IMAGE");
235 } else if (StringBeginsWith(contentType, "video/"_ns)) {
236 key.AssignLiteral("MEDIA");
237 } else if (StringBeginsWith(contentType, "audio/"_ns)) {
238 key.AssignLiteral("MEDIA");
239 } else if (!StringBeginsWith(contentType,
240 nsLiteralCString(UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type"))) {
241 key.AssignLiteral("OTHER");
242 }
243 }
244
245 nsLiteralCString label = CacheDispositionToTelemetryLabel(hitOrMiss);
246 glean::http::cache_disposition.Get(key, label).Add();
247 glean::http::cache_disposition.Get("ALL"_ns, label).Add();
248}
249
250// Computes and returns a SHA1 hash of the input buffer. The input buffer
251// must be a null-terminated string.
252nsresult Hash(const char* buf, nsACString& hash) {
253 nsresult rv;
254
255 nsCOMPtr<nsICryptoHash> hasher =
256 do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID"@mozilla.org/security/hash;1", &rv);
257 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"
, 257); return rv; } } while (false)
;
258
259 rv = hasher->Init(nsICryptoHash::SHA1);
260 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"
, 260); return rv; } } while (false)
;
261
262 rv = hasher->Update(reinterpret_cast<unsigned const char*>(buf), strlen(buf));
263 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"
, 263); return rv; } } while (false)
;
264
265 rv = hasher->Finish(true, hash);
266 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"
, 266); return rv; } } while (false)
;
267
268 return NS_OK;
269}
270
271class CookieVisitor final {
272 public:
273 explicit CookieVisitor(nsHttpResponseHead* aResponseHead) {
274 nsAutoCString cookieHeader;
275 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Set_Cookie, cookieHeader))), 1)))
276 aResponseHead->GetHeader(nsHttp::Set_Cookie, cookieHeader))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Set_Cookie, cookieHeader))), 1)))
) {
277 for (const auto& cookie : cookieHeader.Split('\n')) {
278 mCookieHeaders.AppendElement(cookie);
279 }
280 }
281 }
282
283 ~CookieVisitor() = default;
284
285 const nsTArray<nsCString>& CookieHeaders() const { return mCookieHeaders; }
286
287 private:
288 nsTArray<nsCString> mCookieHeaders;
289};
290
291class CookieObserver final : public nsIObserver,
292 public nsSupportsWeakReference {
293 public:
294 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:
295 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
296
297 static already_AddRefed<CookieObserver> Create(bool aPrivateBrowsing);
298
299 void StealChanges(nsTArray<CookieChange>& aChanges) {
300 aChanges.SwapElements(mChanges);
301 }
302
303 private:
304 CookieObserver() = default;
305 ~CookieObserver() = default;
306
307 nsTArray<CookieChange> mChanges;
308};
309
310NS_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"
, 310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 310
); __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"
, 310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CookieObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 310); __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"
, 310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 310
); __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"
, 310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CookieObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 310); __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"
, 310); 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; }
311
312// static
313already_AddRefed<CookieObserver> CookieObserver::Create(bool aPrivateBrowsing) {
314 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", 314
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 314); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
315
316 RefPtr<CookieObserver> observer = new CookieObserver();
317
318 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
319 if (NS_WARN_IF(!os)NS_warn_if_impl(!os, "!os", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 319)
) {
320 return nullptr;
321 }
322
323 nsresult rv = os->AddObserver(
324 observer, aPrivateBrowsing ? "private-cookie-changed" : "cookie-changed",
325 true);
326 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"
, 326)
) {
327 return nullptr;
328 }
329
330 return observer.forget();
331}
332
333NS_IMETHODIMPnsresult
334CookieObserver::Observe(nsISupports* aSubject, const char* aTopic,
335 const char16_t* aData) {
336 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", 336
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 336); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
337
338 nsCOMPtr<nsICookieNotification> notification = do_QueryInterface(aSubject);
339 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"
, 339); return NS_ERROR_FAILURE; } } while (false)
;
340
341 nsCOMPtr<nsICookie> xpcCookie;
342 nsresult rv = notification->GetCookie(getter_AddRefs(xpcCookie));
343 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"
, 343)
) {
344 return rv;
345 }
346
347 if (!xpcCookie) {
348 return NS_OK;
349 }
350
351 const Cookie& cookie = xpcCookie->AsCookie();
352
353 nsICookieNotification::Action action = notification->GetAction();
354
355 switch (action) {
356 case nsICookieNotification::COOKIE_DELETED:
357 mChanges.AppendElement(CookieChange{/* added */ false, cookie.ToIPC(),
358 cookie.OriginAttributesRef()});
359 break;
360
361 case nsICookieNotification::COOKIE_ADDED:
362 [[fallthrough]];
363 case nsICookieNotification::COOKIE_CHANGED:
364 mChanges.AppendElement(CookieChange{/* added */ true, cookie.ToIPC(),
365 cookie.OriginAttributesRef()});
366 break;
367
368 default:
369 // We don't care about other actions because none of them can be
370 // triggered by the Set-Cookie header.
371 break;
372 }
373
374 return NS_OK;
375}
376
377void MaybeInitializeCookieProcessingGuard(
378 nsHttpChannel* aChannel, CookieServiceParent::CookieProcessingGuard& aGuard,
379 RefPtr<CookieObserver>& aCookieObserver,
380 RefPtr<HttpChannelParent>& aHttpChannelParent, uint32_t aHttpStatus) {
381 nsCOMPtr<nsIParentChannel> parentChannel;
382 NS_QueryNotificationCallbacks(aChannel, parentChannel);
383 aHttpChannelParent = do_QueryObject(parentChannel);
384 if (!aHttpChannelParent) {
385 return;
386 }
387
388 aCookieObserver = CookieObserver::Create(NS_UsePrivateBrowsing(aChannel));
389
390 PNeckoParent* neckoParent = aHttpChannelParent->Manager();
391 if (!neckoParent) {
392 return;
393 }
394
395 PCookieServiceParent* csParent =
396 LoneManagedOrNullAsserts(neckoParent->ManagedPCookieServiceParent());
397 CookieServiceParent* cookieServiceParent =
398 static_cast<CookieServiceParent*>(csParent);
399 if (!cookieServiceParent) {
400 return;
401 }
402
403 // on redirect we don't want to use processing guard
404 // because it will prevent cookies from being set in the
405 // content process that originated the request
406 if (nsHttpChannel::IsRedirectStatus(aHttpStatus)) {
407 return;
408 }
409
410 aGuard.Initialize(cookieServiceParent);
411}
412
413} // unnamed namespace
414
415// We only treat 3xx responses as redirects if they have a Location header and
416// the status code is in a whitelist.
417bool nsHttpChannel::WillRedirect(const nsHttpResponseHead& response) {
418 return IsRedirectStatus(response.Status()) &&
419 response.HasHeader(nsHttp::Location);
420}
421
422nsresult StoreAuthorizationMetaData(nsICacheEntry* entry,
423 nsHttpRequestHead* requestHead);
424
425class MOZ_STACK_CLASS AutoRedirectVetoNotifier {
426 public:
427 explicit AutoRedirectVetoNotifier(nsHttpChannel* channel, nsresult& aRv)
428 : mChannel(channel), mRv(aRv) {
429 if (mChannel->LoadHasAutoRedirectVetoNotifier()) {
430 MOZ_CRASH("Nested AutoRedirectVetoNotifier on the stack")do { do { } while (false); MOZ_ReportCrash("" "Nested AutoRedirectVetoNotifier on the stack"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 430
); AnnotateMozCrashReason("MOZ_CRASH(" "Nested AutoRedirectVetoNotifier on the stack"
")"); do { MOZ_CrashSequence(__null, 430); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
431 mChannel = nullptr;
432 return;
433 }
434
435 mChannel->StoreHasAutoRedirectVetoNotifier(true);
436 }
437 ~AutoRedirectVetoNotifier() { ReportRedirectResult(mRv); }
438 void RedirectSucceeded() { ReportRedirectResult(NS_OK); }
439
440 private:
441 nsHttpChannel* mChannel;
442 bool mCalledReport = false;
443 nsresult& mRv;
444 void ReportRedirectResult(nsresult aRv);
445};
446
447void AutoRedirectVetoNotifier::ReportRedirectResult(nsresult aRv) {
448 if (!mChannel) return;
449
450 if (mCalledReport) {
451 return;
452 }
453 mCalledReport = true;
454
455 mChannel->mRedirectChannel = nullptr;
456
457 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))) {
458 mChannel->RemoveAsNonTailRequest();
459 }
460
461 nsCOMPtr<nsIRedirectResultListener> vetoHook;
462 NS_QueryNotificationCallbacks(mChannel, NS_GET_IID(nsIRedirectResultListener)(nsIRedirectResultListener::kIID),
463 getter_AddRefs(vetoHook));
464
465 nsHttpChannel* channel = mChannel;
466 mChannel = nullptr;
467
468 if (vetoHook) vetoHook->OnRedirectResult(aRv);
469
470 // Drop after the notification
471 channel->StoreHasAutoRedirectVetoNotifier(false);
472}
473
474//-----------------------------------------------------------------------------
475// nsHttpChannel <public>
476//-----------------------------------------------------------------------------
477
478nsHttpChannel::nsHttpChannel() : HttpAsyncAborter<nsHttpChannel>(this) {
479 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)
480 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)
;
481 mChannelCreationTime = PR_Now();
482 mChannelCreationTimestamp = TimeStamp::Now();
483}
484
485nsHttpChannel::~nsHttpChannel() {
486 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"
, 486); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be released on main thread" ")"); do { MOZ_CrashSequence
(__null, 486); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
487 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)
488 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)
;
489 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)
490 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)
;
491
492 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
493 nsCString webExtension;
494 this->GetPropertyAsACString(u"cancelledByExtension"_ns, webExtension);
495 if (!webExtension.IsEmpty()) {
496 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)
497 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)
;
498 }
499 }
500
501 if (mAuthProvider) {
502 DebugOnly<nsresult> rv = mAuthProvider->Disconnect(NS_ERROR_ABORT);
503 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"
, 503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 503); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
504 }
505
506 if (gHttpHandler) {
507 gHttpHandler->RemoveHttpChannel(mChannelId);
508 }
509
510 if (mDictDecompress && mUsingDictionary) {
511 mDictDecompress->UseCompleted();
512 }
513}
514
515nsresult nsHttpChannel::Init(nsIURI* uri, uint32_t caps, nsProxyInfo* proxyInfo,
516 uint32_t proxyResolveFlags, nsIURI* proxyURI,
517 uint64_t channelId, nsILoadInfo* aLoadInfo) {
518 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)
;
519 nsresult rv = HttpBaseChannel::Init(uri, caps, proxyInfo, proxyResolveFlags,
520 proxyURI, channelId, aLoadInfo);
521
522 return rv;
523}
524
525nsresult nsHttpChannel::AddSecurityMessage(const nsAString& aMessageTag,
526 const nsAString& aMessageCategory) {
527 if (mWarningReporter) {
528 RefPtr<HttpChannelSecurityWarningReporter> reporter(mWarningReporter);
529 return reporter->ReportSecurityMessage(aMessageTag, aMessageCategory);
530 }
531 return HttpBaseChannel::AddSecurityMessage(aMessageTag, aMessageCategory);
532}
533
534NS_IMETHODIMPnsresult
535nsHttpChannel::LogBlockedCORSRequest(const nsAString& aMessage,
536 const nsACString& aCategory,
537 bool aIsWarning) {
538 if (mWarningReporter) {
539 RefPtr<HttpChannelSecurityWarningReporter> reporter(mWarningReporter);
540 return reporter->LogBlockedCORSRequest(aMessage, aCategory, aIsWarning);
541 }
542 return NS_ERROR_UNEXPECTED;
543}
544
545NS_IMETHODIMPnsresult
546nsHttpChannel::LogMimeTypeMismatch(const nsACString& aMessageName,
547 bool aWarning, const nsAString& aURL,
548 const nsAString& aContentType) {
549 if (mWarningReporter) {
550 RefPtr<HttpChannelSecurityWarningReporter> reporter(mWarningReporter);
551 return reporter->LogMimeTypeMismatch(aMessageName, aWarning, aURL,
552 aContentType);
553 }
554 return NS_ERROR_UNEXPECTED;
555}
556
557//-----------------------------------------------------------------------------
558// nsHttpChannel <private>
559//-----------------------------------------------------------------------------
560
561void nsHttpChannel::AddStorageAccessHeadersToRequest() {
562 if (!StaticPrefs::dom_storage_access_enabled() ||
563 !StaticPrefs::dom_storage_access_headers_enabled()) {
564 return;
565 }
566
567 // check if request is eligible for storage-access
568 uint32_t cookiePolicy = 0;
569 if (mLoadInfo->GetCookiePolicy(&cookiePolicy) != NS_OK) {
570 return;
571 }
572 if (cookiePolicy != nsILoadInfo::SEC_COOKIES_INCLUDE) {
573 return;
574 }
575
576 // check whether we have storage-access permission set in channel
577 nsILoadInfo::StoragePermissionState storageAccess =
578 AntiTrackingUtils::GetStoragePermissionStateInParent(this);
579
580 switch (storageAccess) {
581 case nsILoadInfo::HasStoragePermission:
582 case nsILoadInfo::StoragePermissionAllowListed:
583 SetRequestHeader(nsHttp::Sec_Fetch_Storage_Access.val(), "active"_ns,
584 false);
585 break;
586 case nsILoadInfo::InactiveStoragePermission:
587 SetRequestHeader(nsHttp::Sec_Fetch_Storage_Access.val(), "inactive"_ns,
588 false);
589 break;
590 case nsILoadInfo::DisabledStoragePermission:
591 SetRequestHeader(nsHttp::Sec_Fetch_Storage_Access.val(), "none"_ns,
592 false);
593 break;
594 case nsILoadInfo::NoStoragePermission:
595 break;
596 }
597}
598
599bool nsHttpChannel::StorageAccessReloadedChannel() {
600 return LoadStorageAccessReloadChannel();
601}
602
603void nsHttpChannel::PrimeSuspendAfterExamineResponse() {
604 mSuspendAfterExamineResponse = Some(true);
605}
606
607void nsHttpChannel::CancelSuspendOrResumeAfterExamineResponse() {
608 if (mSuspendAfterExamineResponse.isNothing()) {
609 return;
610 }
611 mSuspendAfterExamineResponse.ref() = false;
612 if (mSuspendedForExamineResponse.exchange(false)) {
613 Resume();
614 }
615}
616
617void nsHttpChannel::MaybeSuspendAfterExamineResponse() {
618 if (mSuspendAfterExamineResponse.isNothing()) {
619 return;
620 }
621 bool oldValue = mSuspendAfterExamineResponse.ref().exchange(false);
622 if (oldValue) {
623 mSuspendedForExamineResponse = true;
624 Suspend();
625 }
626}
627
628nsresult nsHttpChannel::PrepareToConnect() {
629 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)
;
630
631 // This may be async; the dictionary headers may need to fetch an origin
632 // dictionary cache entry from disk before adding the headers. We can
633 // continue with channel creation, and just block on this being done later
634 AUTO_PROFILER_FLOW_MARKER("nsHttpHandler::AddAcceptAndDictionaryHeaders",::mozilla::AutoProfilerFlowMarker raiiObject635( "nsHttpHandler::AddAcceptAndDictionaryHeaders"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
635 NETWORK, Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject635( "nsHttpHandler::AddAcceptAndDictionaryHeaders"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
636 // AddAcceptAndDictionaryHeaders must call this->Suspend before kicking
637 // off the async operation that can result in calling the lambda (which
638 // will Resume), to avoid a race condition.
639 nsresult rv = gHttpHandler->AddAcceptAndDictionaryHeaders(
640 mURI, mLoadInfo->GetExternalContentPolicyType(), &mRequestHead, IsHTTPS(),
641 this, nsHttpChannel::StaticSuspend,
642 [self = RefPtr(this)](bool aNeedsResume, DictionaryCacheEntry* aDict) {
643 if (aNeedsResume) {
644 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)
;
645 self->Resume();
646 }
647 if (!aDict) {
648 return true;
649 }
650 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)
651 ("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)
652 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)
;
653 AUTO_PROFILER_FLOW_MARKER(::mozilla::AutoProfilerFlowMarker raiiObject656( "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "
"Available-Dictionary", ::mozilla::baseprofiler::category::NETWORK
, Flow::FromPointer(self))
654 "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "::mozilla::AutoProfilerFlowMarker raiiObject656( "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "
"Available-Dictionary", ::mozilla::baseprofiler::category::NETWORK
, Flow::FromPointer(self))
655 "Available-Dictionary",::mozilla::AutoProfilerFlowMarker raiiObject656( "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "
"Available-Dictionary", ::mozilla::baseprofiler::category::NETWORK
, Flow::FromPointer(self))
656 NETWORK, Flow::FromPointer(self))::mozilla::AutoProfilerFlowMarker raiiObject656( "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "
"Available-Dictionary", ::mozilla::baseprofiler::category::NETWORK
, Flow::FromPointer(self))
;
657 // These need to be set before calling prefetch
658 self->mDictDecompress = aDict;
659 self->mDictDecompress->InUse();
660 self->mUsingDictionary = true;
661 // If this fails, we won't add the dictionary and the
662 // Available-Dictionary header.
663 RefPtr<LoadContextInfo> lci = GetLoadContextInfo(self);
664 if (NS_SUCCEEDED(aDict->Prefetch(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 lci, self->mShouldSuspendForDictionary,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 [self](nsresult aResult) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 // this is called when the prefetch is complete to((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 // un-Suspend the channel((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 PROFILER_MARKER("Dictionary Prefetch", NETWORK,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 MarkerTiming::IntervalEnd(), FlowMarker,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 Flow::FromPointer(self));((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 if (NS_FAILED(aResult)) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 LOG(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 ("nsHttpChannel::SetupChannelForTransaction [this=%p] "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 "Dictionary prefetch failed: 0x%08" PRIx32,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 self.get(), static_cast<uint32_t>(aResult)));((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 if (self->mUsingDictionary) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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->mDictDecompress->UseCompleted();((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 self->mUsingDictionary = false;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 self->mDictDecompress = nullptr;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 if (self->mSuspendedForDictionary) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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->mSuspendedForDictionary = false;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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->Cancel(aResult);((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 self->Resume();((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 return;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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->mDictDecompress) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 // The request already completed and released the dictionary((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 // (SetDecompressDictionary(nullptr) from the compress((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 // converter's OnStopRequest) before this async prefetch((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 // callback ran. Nothing left to resume.((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 return;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 MOZ_ASSERT(self->mDictDecompress->DictionaryReady());((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 if (self->mSuspendedForDictionary) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 LOG(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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 ("nsHttpChannel::SetupChannelForTransaction [this=%p] "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
700 "Resuming channel "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
701 "suspended for Dictionary",((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
702 self.get()));((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
703 self->mSuspendedForDictionary = false;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
704 self->Resume();((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
705 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
706 }))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 696
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 696); __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)))
) {
707 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)
708 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)
709 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)
;
710 return true;
711 }
712 // Need to undo these if we're not going to be able to use the dict
713 self->mDictDecompress->UseCompleted();
714 self->mDictDecompress = nullptr;
715 self->mUsingDictionary = false;
716 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)
;
717 return false;
718 });
719 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
720
721 // notify "http-on-modify-request-before-cookies" observers
722 gHttpHandler->OnModifyRequestBeforeCookies(this);
723
724 if (mStaleRevalidation) {
725 // This is a revalidating channel.
726 // The cookies (user set cookies + cookies from the cookeservice) are
727 // already copied to the request headers when opening this channel in
728 // PerformBackgroundCacheRevalidationNow().
729 } else {
730 AddCookiesToRequest();
731 }
732
733#if defined(XP_WIN) || defined(XP_MACOSX)
734
735 auto prefEnabledForCurrentContainer = [&]() {
736 uint32_t containerId = mLoadInfo->GetOriginAttributes().mUserContextId;
737 // Make sure that the default container ID is 0
738 static_assert(nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID == 0);
739
740 nsAutoCString prefName;
741# ifdef XP_WIN
742 prefName = nsPrintfCString("network.http.windows-sso.container-enabled.%u",
743 containerId);
744# endif
745
746# ifdef XP_MACOSX
747 prefName = nsPrintfCString(
748 "network.http.microsoft-entra-sso.container-enabled.%u", containerId);
749# endif
750
751 bool enabled = false;
752 Preferences::GetBool(prefName.get(), &enabled);
753
754 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)
;
755
756 return enabled;
757 };
758
759#endif // defined(XP_WIN) || defined(XP_MACOSX)
760
761#ifdef XP_WIN
762
763 // If Windows 10 SSO is enabled, we potentially add auth
764 // information to secure top level loads (DOCUMENTs) and iframes
765 // (SUBDOCUMENTs) that aren't anonymous or private browsing.
766 if (StaticPrefs::network_http_windows_sso_enabled() &&
767 mURI->SchemeIs("https") && !(mLoadFlags & LOAD_ANONYMOUS) &&
768 !mPrivateBrowsing) {
769 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
770 if ((type == ExtContentPolicy::TYPE_DOCUMENT ||
771 type == ExtContentPolicy::TYPE_SUBDOCUMENT) &&
772 prefEnabledForCurrentContainer()) {
773 AddWindowsSSO(this);
774 }
775 }
776#endif
777
778#ifdef XP_MACOSX
779
780 auto isUriMSAuthority = [&]() {
781 nsAutoCString endPoint;
782 nsresult rv = mURI->GetHost(endPoint);
783 if (!NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
784 return false;
785 }
786 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)
;
787
788 return gHttpHandler->IsHostMSAuthority(endPoint);
789 };
790
791 // If macOS SSO is enabled, we potentially add auth
792 // information to secure top level loads (DOCUMENTs) and iframes
793 // (SUBDOCUMENTs) that aren't anonymous or private browsing.
794 if (StaticPrefs::network_http_microsoft_entra_sso_enabled() &&
795 mURI->SchemeIs("https") && !(mLoadFlags & LOAD_ANONYMOUS) &&
796 !mPrivateBrowsing) {
797 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
798 if ((type == ExtContentPolicy::TYPE_DOCUMENT ||
799 type == ExtContentPolicy::TYPE_SUBDOCUMENT) &&
800 prefEnabledForCurrentContainer() && isUriMSAuthority()) {
801 nsMainThreadPtrHandle<nsHttpChannel> self(
802 new nsMainThreadPtrHolder<nsHttpChannel>(
803 "nsHttpChannel::PrepareToConnect::self", this));
804 auto resultCallback = [self(self)]() {
805 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", 805
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 805); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
806 nsresult rv = self->ContinuePrepareToConnect();
807 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
808 self->CloseCacheEntry(false);
809 (void)self->AsyncAbort(rv);
810 }
811 };
812
813 nsresult rv = AddMicrosoftEntraSSO(this, std::move(resultCallback));
814
815 // Returns NS_OK if performRequests is called in MicrosoftEntraSSOUtils
816 // This temporarily stops the channel setup for the delegate.
817 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
818 return rv;
819 }
820 }
821 }
822
823#endif
824
825 return ContinuePrepareToConnect();
826}
827
828nsresult nsHttpChannel::ContinuePrepareToConnect() {
829 // notify "http-on-modify-request" observers
830 CallOnModifyRequestObservers();
831
832 return CallOrWaitForResume(
833 [](auto* self) { return self->OnBeforeConnect(); });
834}
835
836void nsHttpChannel::HandleContinueCancellingByURLClassifier(
837 nsresult aErrorCode) {
838 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", 838
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 838); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
839 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"
, 839); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 839); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
840
841 if (mSuspendCount) {
842 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)
843 ("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)
844 "[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)
845 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
846 mCallOnResume = [aErrorCode](nsHttpChannel* self) {
847 self->HandleContinueCancellingByURLClassifier(aErrorCode);
848 return NS_OK;
849 };
850 return;
851 }
852
853 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)
854 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
855 ContinueCancellingByURLClassifier(aErrorCode);
856}
857
858void nsHttpChannel::SetPriorityHeader() {
859 nsAutoCString userSetPriority;
860 (void)GetRequestHeader("Priority"_ns, userSetPriority);
861 if (!userSetPriority.IsEmpty()) {
862 // If the Priority header is set by the user, do not override it.
863 return;
864 }
865
866 uint8_t urgency =
867 nsHttpHandler::UrgencyFromCoSFlags(mClassOfService.Flags(), mPriority);
868 bool incremental = mClassOfService.Incremental();
869
870 nsPrintfCString value(
871 "%s", urgency != 3 ? nsPrintfCString("u=%d", urgency).get() : "");
872
873 if (incremental) {
874 if (!value.IsEmpty()) {
875 value.Append(", ");
876 }
877 value.Append("i");
878 }
879
880 if (!value.IsEmpty()) {
881 SetRequestHeader("Priority"_ns, value, false);
882 }
883}
884
885nsresult nsHttpChannel::OnBeforeConnect() {
886 nsresult rv = NS_OK;
887
888 // Check if request was cancelled during suspend AFTER on-modify-request
889 if (mCanceled) {
890 return mStatus;
891 }
892
893 // Check to see if we should redirect this channel elsewhere by
894 // nsIHttpChannel.redirectTo API request
895 if (mAPIRedirectTo) {
896 return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
897 }
898
899 // Note that we are only setting the "Upgrade-Insecure-Requests" request
900 // header for *all* navigational requests instead of all requests as
901 // defined in the spec, see:
902 // https://www.w3.org/TR/upgrade-insecure-requests/#preference
903 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
904
905 if (type == ExtContentPolicy::TYPE_DOCUMENT ||
906 type == ExtContentPolicy::TYPE_SUBDOCUMENT) {
907 rv = SetRequestHeader("Upgrade-Insecure-Requests"_ns, "1"_ns, false);
908 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"
, 908); return rv; } } while (false)
;
909 }
910
911 if (LoadAuthRedirectedChannel()) {
912 // This channel is a result of a redirect due to auth retry
913 // We have already checked for HSTS upgarde in the redirecting channel.
914 // We can safely skip those checks
915 return ContinueOnBeforeConnect(false, rv);
916 }
917
918 SecFetch::AddSecFetchHeader(this);
919
920 // Check to see if we should redirect this channel to the unstripped URI. To
921 // revert the query stripping if the loading channel is in the content
922 // blocking allow list.
923 if (ContentBlockingAllowList::Check(this)) {
924 nsCOMPtr<nsIURI> unstrippedURI;
925 mLoadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
926
927 if (unstrippedURI) {
928 return AsyncCall(&nsHttpChannel::HandleAsyncRedirectToUnstrippedURI);
929 }
930 }
931
932 nsCOMPtr<nsIPrincipal> resultPrincipal;
933 if (!mURI->SchemeIs("https")) {
934 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
935 this, getter_AddRefs(resultPrincipal));
936 }
937
938 // Check if we already know about the HSTS status of the host
939 nsISiteSecurityService* sss = gHttpHandler->GetSSService();
940 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"
, 940); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
941 bool isSecureURI;
942 OriginAttributes originAttributes;
943 if (!StoragePrincipalHelper::GetOriginAttributesForHSTS(this,
944 originAttributes)) {
945 return NS_ERROR_FAILURE;
946 }
947 rv = sss->IsSecureURI(mURI, originAttributes, &isSecureURI);
948 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"
, 948); return rv; } } while (false)
;
949 // Save that on the loadInfo so it can later be consumed by
950 // SecurityInfo.sys.mjs
951 mLoadInfo->SetHstsStatus(isSecureURI);
952
953 // If bypassing the cache and we're forced offline
954 // we can just return the error here.
955 if (IsForcedOffline() &&
956 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
957 return NS_ERROR_OFFLINE;
958 }
959
960 // At this point it is no longer possible to call
961 // HttpBaseChannel::UpgradeToSecure.
962 StoreUpgradableToSecure(false);
963 bool shouldUpgrade = LoadUpgradeToSecure();
964 if (mURI->SchemeIs("http")) {
965 OriginAttributes originAttributes;
966 if (!StoragePrincipalHelper::GetOriginAttributesForHSTS(this,
967 originAttributes)) {
968 return NS_ERROR_FAILURE;
969 }
970
971 if (!shouldUpgrade) {
972 // Make sure http channel is released on main thread.
973 // See bug 1539148 for details.
974 nsMainThreadPtrHandle<nsHttpChannel> self(
975 new nsMainThreadPtrHolder<nsHttpChannel>(
976 "nsHttpChannel::OnBeforeConnect::self", this));
977 auto resultCallback = [self(self)](bool aResult, nsresult aStatus) {
978 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", 978
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 978); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
979
980 nsresult rv = self->MaybeUseHTTPSRRForUpgrade(aResult, aStatus);
981 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
982 self->CloseCacheEntry(false);
983 (void)self->AsyncAbort(rv);
984 }
985 };
986
987 bool willCallback = false;
988 rv = NS_ShouldSecureUpgrade(mURI, mLoadInfo, this, resultPrincipal,
989 LoadAllowSTS(), originAttributes,
990 shouldUpgrade, std::move(resultCallback),
991 willCallback);
992 // If the request gets upgraded because of the HTTPS-Only mode, but no
993 // event listener has been registered so far, we want to do that here.
994 uint32_t httpOnlyStatus = mLoadInfo->GetHttpsOnlyStatus();
995 if (httpOnlyStatus &
996 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED) {
997 RefPtr<nsHTTPSOnlyStreamListener> httpsOnlyListener =
998 new nsHTTPSOnlyStreamListener(mListener, mLoadInfo);
999 mListener = httpsOnlyListener;
1000
1001 httpOnlyStatus ^=
1002 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED;
1003 httpOnlyStatus |= nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED;
1004 mLoadInfo->SetHttpsOnlyStatus(httpOnlyStatus);
1005 }
1006 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)
1007 ("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)
1008 "[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)
1009 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)
;
1010
1011 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || MOZ_UNLIKELY(willCallback)(__builtin_expect(!!(willCallback), 0))) {
1012 return rv;
1013 }
1014 }
1015 }
1016
1017 return MaybeUseHTTPSRRForUpgrade(shouldUpgrade, NS_OK);
1018}
1019
1020// Returns true if the network connectivity checker indicated
1021// that HTTPS records can be resolved on this network - false otherwise.
1022// When TRR is enabled, we always return true, as resolving HTTPS
1023// records don't depend on the network.
1024static bool canUseHTTPSRRonNetwork(bool& aTRREnabled) {
1025 // Respect the pref.
1026 if (StaticPrefs::network_dns_force_use_https_rr()) {
1027 aTRREnabled = true;
1028 return true;
1029 }
1030
1031 aTRREnabled = false;
1032
1033 if (nsCOMPtr<nsIDNSService> dns = mozilla::components::DNS::Service()) {
1034 nsIDNSService::ResolverMode mode;
1035 // If the browser is currently using TRR/DoH, then it can
1036 // definitely resolve HTTPS records.
1037 if (NS_SUCCEEDED(dns->GetCurrentTrrMode(&mode))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dns->GetCurrentTrrMode
(&mode))), 1)))
) {
1038 if (mode == nsIDNSService::MODE_TRRFIRST) {
1039 RefPtr<TRRService> trr = TRRService::Get();
1040 if (trr && trr->IsConfirmed()) {
1041 aTRREnabled = true;
1042 }
1043 } else if (mode == nsIDNSService::MODE_TRRONLY) {
1044 aTRREnabled = true;
1045 }
1046 if (aTRREnabled) {
1047 return true;
1048 }
1049 }
1050 }
1051
1052 // With Happy Eyeballs enabled we can allow native HTTPS RR queries: HE's
1053 // resolution-delay timer lets connection attempts proceed using the A/AAAA
1054 // results even when the native HTTPS RR lookup is slow or blocked.
1055 if (StaticPrefs::network_http_happy_eyeballs_enabled()) {
1056 return true;
1057 }
1058
1059 if (RefPtr<NetworkConnectivityService> ncs =
1060 NetworkConnectivityService::GetSingleton()) {
1061 nsINetworkConnectivityService::ConnectivityState state;
1062 if (NS_SUCCEEDED(ncs->GetDNS_HTTPS(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetDNS_HTTPS
(&state))), 1)))
&&
1063 state == nsINetworkConnectivityService::NOT_AVAILABLE) {
1064 return false;
1065 }
1066 }
1067 return true;
1068}
1069
1070nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade,
1071 nsresult aStatus) {
1072 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
1073 return aStatus;
1074 }
1075
1076 bool forceOffline = IsForcedOffline();
1077
1078 if (mURI->SchemeIs("https") || aShouldUpgrade || !LoadUseHTTPSSVC() ||
1079 forceOffline) {
1080 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
1081 }
1082
1083 auto shouldSkipUpgradeWithHTTPSRR = [&]() -> bool {
1084 if (mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) {
1085 return true;
1086 }
1087
1088 // Skip using HTTPS RR to upgrade when this is not a top-level load and the
1089 // loading principal is http.
1090 if ((mLoadInfo->GetExternalContentPolicyType() !=
1091 ExtContentPolicy::TYPE_DOCUMENT) &&
1092 (mLoadInfo->GetLoadingPrincipal() &&
1093 mLoadInfo->GetLoadingPrincipal()->SchemeIs("http"))) {
1094 return true;
1095 }
1096
1097 // If the network connectivity checker indicates the network is
1098 // blocking HTTPS requests, then we should skip them so we don't
1099 // needlessly wait for a timeout.
1100 bool trrEnabled = false;
1101 if (!canUseHTTPSRRonNetwork(trrEnabled)) {
1102 return true;
1103 }
1104
1105 // Don't block the channel when TRR is not used.
1106 if (!trrEnabled) {
1107 return true;
1108 }
1109
1110 auto dnsStrategy = ComputeProxyDNSStrategy();
1111 if (dnsStrategy != nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN) {
1112 return true;
1113 }
1114
1115 nsAutoCString uriHost;
1116 mURI->GetAsciiHost(uriHost);
1117
1118 return gHttpHandler->IsHostExcludedForHTTPSRR(uriHost);
1119 };
1120
1121 if (shouldSkipUpgradeWithHTTPSRR()) {
1122 StoreUseHTTPSSVC(false);
1123 // If the website does not want to use HTTPS RR, we should set
1124 // NS_HTTP_DISALLOW_HTTPS_RR. This is for avoiding HTTPS RR being used by
1125 // the transaction.
1126 DisallowHTTPSRR(mCaps);
1127 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
1128 }
1129
1130 if (mHTTPSSVCRecord.isSome()) {
1131 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)
1132 "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)
1133 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
1134 StoreWaitHTTPSSVCRecord(false);
1135 bool hasHTTPSRR = (mHTTPSSVCRecord.ref() != nullptr);
1136 return ContinueOnBeforeConnect(hasHTTPSRR, aStatus, hasHTTPSRR);
1137 }
1138
1139 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)
1140 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
1141
1142 OriginAttributes originAttributes;
1143 StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(this, originAttributes);
1144
1145 RefPtr<nsDNSPrefetch> resolver =
1146 new nsDNSPrefetch(mURI, originAttributes, nsIRequest::GetTRRMode());
1147 nsWeakPtr weakPtrThis(
1148 do_GetWeakReference(static_cast<nsIHttpChannel*>(this)));
1149 nsresult rv = resolver->FetchHTTPSSVC(
1150 mCaps & NS_HTTP_REFRESH_DNS(1 << 3), !LoadUseHTTPSSVC(),
1151 [weakPtrThis](nsIDNSHTTPSSVCRecord* aRecord) {
1152 nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(weakPtrThis);
1153 RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(channel);
1154 if (httpChannelImpl) {
1155 httpChannelImpl->OnHTTPSRRAvailable(aRecord);
1156 }
1157 });
1158 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1159 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)
1160 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)
;
1161 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
1162 }
1163
1164 StoreWaitHTTPSSVCRecord(true);
1165 return NS_OK;
1166}
1167
1168nsresult nsHttpChannel::ContinueOnBeforeConnect(bool aShouldUpgrade,
1169 nsresult aStatus,
1170 bool aUpgradeWithHTTPSRR) {
1171 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)
1172 ("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)
1173 "[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)
1174 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)
;
1175
1176 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", 1176
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadWaitHTTPSSVCRecord()"
")"); do { MOZ_CrashSequence(__null, 1176); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1177
1178 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
1179 return aStatus;
1180 }
1181
1182 if (aShouldUpgrade && !mURI->SchemeIs("https")) {
1183 // only set HTTPS_RR to be responsbile for the upgrade in the loadinfo
1184 // if it actually was responsible, otherwise the correct flag is
1185 // already present in the loadinfo.
1186 if (aUpgradeWithHTTPSRR) {
1187 mLoadInfo->SetHttpsUpgradeTelemetry(nsILoadInfo::HTTPS_RR);
1188 NS_LogSecureUpgradeToConsole(mURI, mLoadInfo, this, "HTTPS RR"_ns);
1189 }
1190 return AsyncCall(&nsHttpChannel::HandleAsyncRedirectChannelToHttps);
1191 }
1192
1193 // ensure that we are using a valid hostname
1194 if (!net_IsValidDNSHost(nsDependentCString(mConnectionInfo->Origin()))) {
1195 return NS_ERROR_UNKNOWN_HOST;
1196 }
1197
1198 if (mUpgradeProtocolCallback) {
1199 // Websockets can run over HTTP/2, but other upgrades can't.
1200 if (mUpgradeProtocol.EqualsLiteral("websocket") &&
1201 StaticPrefs::network_http_http2_websockets()) {
1202 // Need to tell the conn manager that we're ok with http/2 even with
1203 // the allow keepalive bit not set. That bit needs to stay off,
1204 // though, in case we end up having to fallback to http/1.1 (where
1205 // we absolutely do want to disable keepalive).
1206 mCaps |= NS_HTTP_ALLOW_SPDY_WITHOUT_KEEPALIVE(1 << 15);
1207 } else {
1208 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
1209 }
1210 // Upgrades cannot use HTTP/3.
1211 // TODO: When mUpgradeProtocolCallback is not null, we should allow HTTP/3
1212 // for connect-udp.
1213 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
1214 // NS_HTTP_STICKY_CONNECTION breaks the (non-Happy-Eyeballs) HTTPS RR
1215 // fallback mechanism, which restarts the transaction to fall back. Happy
1216 // Eyeballs instead races endpoints (honoring the HTTPS RR port, hints and
1217 // ALPN) and dispatches the sticky upgrade onto the winner with no restart,
1218 // so it can safely use HTTPS RR. Only disallow HTTPS RR for upgrades that
1219 // are not handled by Happy Eyeballs.
1220 if (!(mCaps & NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30))) {
1221 DisallowHTTPSRR(mCaps);
1222 }
1223 }
1224
1225 if (LoadIsTRRServiceChannel()) {
1226 mCaps |= NS_HTTP_LARGE_KEEPALIVE(1 << 1);
1227 DisallowHTTPSRR(mCaps);
1228 }
1229
1230 if (mTransactionSticky) {
1231 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", 1231
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadAuthRedirectedChannel()"
")"); do { MOZ_CrashSequence(__null, 1231); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1232 // this means this is a redirected channel channel due to auth retry and a
1233 // connection based auth scheme was used
1234 // we have a reference to the old-transaction with sticky connection which
1235 // we need to use
1236 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
1237 }
1238
1239 mCaps |= NS_HTTP_TRR_FLAGS_FROM_MODE(nsIRequest::GetTRRMode())((static_cast<uint32_t>(nsIRequest::GetTRRMode()) &
3) << 19)
;
1240
1241 // Finalize ConnectionInfo flags before SpeculativeConnect
1242 mConnectionInfo =
1243 mConnectionInfo->Mutate()
1244 .SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0)
1245 .SetPrivate(mPrivateBrowsing)
1246 .SetNoSpdy(mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7))
1247 .SetBeConservative((mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) ||
1248 LoadBeConservative())
1249 .SetTlsFlags(mTlsFlags)
1250 .SetIsTrrServiceChannel(LoadIsTRRServiceChannel())
1251 .SetTRRMode(nsIRequest::GetTRRMode())
1252 .SetIPv4Disabled(mCaps & NS_HTTP_DISABLE_IPV4(1 << 17))
1253 .SetIPv6Disabled(mCaps & NS_HTTP_DISABLE_IPV6(1 << 18))
1254 .SetHttp3Policy((mCaps & NS_HTTP_DISALLOW_HTTP3(1 << 21))
1255 ? Http3Policy::Disabled
1256 : Http3Policy::Allowed)
1257 .SetAnonymousAllowClientCert(
1258 (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) != 0)
1259 .Finalize();
1260
1261 if (mWebTransportSessionEventListener) {
1262 nsTArray<RefPtr<nsIWebTransportHash>> aServerCertHashes;
1263 nsresult rv;
1264 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
1265 do_QueryInterface(mWebTransportSessionEventListener, &rv);
1266 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"
, 1266); return rv; } } while (false)
;
1267
1268 wtconSettings->GetServerCertificateHashes(aServerCertHashes);
1269 gHttpHandler->ConnMgr()->StoreServerCertHashes(
1270 mConnectionInfo, gHttpHandler->IsHttp2Excluded(mConnectionInfo),
1271 !Http3Allowed(), std::move(aServerCertHashes));
1272 }
1273
1274 if (ShouldIntercept()) {
1275 return RedirectToInterceptedChannel();
1276 }
1277
1278 // notify "http-on-before-connect" observers
1279 gHttpHandler->OnBeforeConnect(this);
1280
1281 return CallOrWaitForResume([](auto* self) { return self->Connect(); });
1282}
1283
1284class MOZ_STACK_CLASS AddResponseHeadersToResponseHead final
1285 : public nsIHttpHeaderVisitor {
1286 public:
1287 explicit AddResponseHeadersToResponseHead(nsHttpResponseHead* aResponseHead)
1288 : mResponseHead(aResponseHead) {}
1289
1290 NS_IMETHODvirtual nsresult VisitHeader(const nsACString& aHeader,
1291 const nsACString& aValue) override {
1292 nsAutoCString headerLine = aHeader + ": "_ns + aValue;
1293 DebugOnly<nsresult> rv = mResponseHead->ParseHeaderLine(headerLine);
1294 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"
, 1294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1294); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1295
1296 return NS_OK;
1297 }
1298
1299 NS_IMETHODvirtual nsresult QueryInterface(REFNSIIDconst nsIID& aIID, void** aInstancePtr) override;
1300
1301 // Stub AddRef/Release since this is a stack class.
1302 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType AddRef(void) override {
1303 return ++mRefCnt;
1304 }
1305
1306 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType Release(void) override {
1307 return --mRefCnt;
1308 }
1309
1310 virtual ~AddResponseHeadersToResponseHead() {
1311 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"
, 1311); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mRefCnt == 0"
")"); do { MOZ_CrashSequence(__null, 1311); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1312 }
1313
1314 private:
1315 nsHttpResponseHead* mResponseHead;
1316
1317 nsrefcnt mRefCnt = 0;
1318};
1319
1320NS_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"
, 1320); 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; }
1321
1322nsresult nsHttpChannel::HandleOverrideResponse() {
1323 // Start building a response with the data from mOverrideResponse.
1324 mResponseHead = MakeUnique<nsHttpResponseHead>();
1325
1326 // Apply override response status code and status text.
1327 uint32_t statusCode;
1328 nsresult rv = mOverrideResponse->GetResponseStatus(&statusCode);
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 nsAutoCString statusText;
1332 rv = mOverrideResponse->GetResponseStatusText(statusText);
1333 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"
, 1333); return rv; } } while (false)
;
1334
1335 // Hardcoding protocol HTTP/1.1
1336 nsPrintfCString line("HTTP/1.1 %u %s", statusCode, statusText.get());
1337 rv = mResponseHead->ParseStatusLine(line);
1338 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"
, 1338); return rv; } } while (false)
;
1339
1340 // Apply override response headers.
1341 AddResponseHeadersToResponseHead visitor(mResponseHead.get());
1342 rv = mOverrideResponse->VisitResponseHeaders(&visitor);
1343 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"
, 1343); return rv; } } while (false)
;
1344
1345 // This block parses the cookie header, collects any cookie changes,
1346 // and sends them to the parent actor.
1347 {
1348 RefPtr<HttpChannelParent> httpParent;
1349 RefPtr<CookieObserver> cookieObserver;
1350
1351 CookieServiceParent::CookieProcessingGuard cookieProcessingGuard;
1352 MaybeInitializeCookieProcessingGuard(
1353 this, cookieProcessingGuard, cookieObserver, httpParent, statusCode);
1354
1355 // Handle Set-Cookie headers as if the response was from networking.
1356 CookieVisitor cookieVisitor(mResponseHead.get());
1357 SetCookieHeaders(cookieVisitor.CookieHeaders());
1358
1359 if (cookieObserver) {
1360 nsTArray<CookieChange> cookieChanges;
1361 cookieObserver->StealChanges(cookieChanges);
1362
1363 if (!cookieChanges.IsEmpty()) {
1364 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"
, 1364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpParent"
")"); do { MOZ_CrashSequence(__null, 1364); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1365 httpParent->SetCookieChanges(std::move(cookieChanges));
1366 }
1367 }
1368 }
1369
1370 rv = ProcessWAICTHeader();
1371 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1372 return rv;
1373 }
1374
1375 if (NS_FAILED(ProcessSecurityHeaders())((bool)(__builtin_expect(!!(NS_FAILED_impl(ProcessSecurityHeaders
())), 0)))
) {
1376 NS_WARNING("ProcessSecurityHeaders failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSecurityHeaders failed, continuing load."
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1376)
;
1377 }
1378
1379 if ((statusCode < 500) && (statusCode != 421)) {
1380 ProcessAltService();
1381 }
1382
1383 if (WillRedirect(*mResponseHead)) {
1384 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
1385 // to avoid event dispatching latency.
1386 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)
;
1387 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
1388 }
1389
1390 nsAutoCString body;
1391 rv = mOverrideResponse->GetResponseBody(body);
1392 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"
, 1392); return rv; } } while (false)
;
1393
1394 nsCOMPtr<nsIInputStream> stringStream;
1395 rv = NS_NewCStringInputStream(getter_AddRefs(stringStream), body);
1396 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"
, 1396); return rv; } } while (false)
;
1397 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), stringStream, 0, 0,
1398 true);
1399 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1400 stringStream->Close();
1401 return rv;
1402 }
1403
1404 rv = mCachePump->AsyncRead(this);
1405 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1406
1407 return NS_OK;
1408}
1409
1410nsresult nsHttpChannel::Connect() {
1411 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)
;
1412
1413 if (mAPIRedirectTo) {
1414 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)
1415 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)
;
1416
1417 nsresult rv = StartRedirectChannelToURI(
1418 mAPIRedirectTo->first(),
1419 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_PERMANENT |
1420 nsIChannelEventSink::REDIRECT_TRANSPARENT
1421 : nsIChannelEventSink::REDIRECT_PERMANENT);
1422 mAPIRedirectTo = Nothing();
1423 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1424 return NS_OK;
1425 }
1426 return NS_ERROR_FAILURE;
1427 }
1428
1429 // If mOverrideResponse is set, bypass the rest of the connection and reply
1430 // immediately with a response built using the data from mOverrideResponse.
1431 if (mOverrideResponse) {
1432 return HandleOverrideResponse();
1433 }
1434
1435 // Don't allow resuming when cache must be used
1436 if (LoadResuming() && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
1437 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)
;
1438 return NS_ERROR_DOCUMENT_NOT_CACHED;
1439 }
1440
1441 // Step 8.18 of HTTP-network-or-cache fetch
1442 // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
1443 nsAutoCString rangeVal;
1444 if (NS_SUCCEEDED(GetRequestHeader("Range"_ns, rangeVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Range"_ns, rangeVal))), 1)))
) {
1445 SetRequestHeader("Accept-Encoding"_ns, "identity"_ns, false);
1446 }
1447
1448 if (mRequestHead.IsPost() || mRequestHead.IsPatch()) {
1449 // If the post id is already set then this is an attempt to replay
1450 // a post/patch transaction via the cache. Otherwise, we need a unique
1451 // post id for this transaction.
1452 if (mPostID == 0) {
1453 mPostID = gHttpHandler->GenerateUniqueID();
1454 }
1455
1456 if (StaticPrefs::network_http_idempotencyKey_enabled() &&
1457 !mRequestHead.HasHeader(nsHttp::Idempotency_Key)) {
1458 // check if we need to add
1459 // idempotency-key header
1460 // See Bug 1830022 for more details
1461 nsAutoCString key;
1462 gHttpHandler->GenerateIdempotencyKeyForPost(mPostID, mLoadInfo, key);
1463 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", 1464
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
")"); do { MOZ_CrashSequence(__null, 1464); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1464 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", 1464
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
")"); do { MOZ_CrashSequence(__null, 1464); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1465 }
1466 }
1467
1468#ifdef MOZ_WIDGET_ANDROID
1469 bool val = false;
1470 if (nsIOService::ShouldAddAdditionalSearchHeaders(mURI, &val)) {
1471 SetRequestHeader("X-Search-Subdivision"_ns, val ? "1"_ns : "0"_ns, false);
1472 }
1473#endif
1474
1475 bool isTrackingResource = IsThirdPartyTrackingResource();
1476 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)
1477 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)
1478 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)
;
1479
1480 if (isTrackingResource) {
1481 AddClassFlags(nsIClassOfService::Tail);
1482 }
1483
1484 if (WaitingForTailUnblock()) {
1485 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", 1485
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 1485); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1486 mOnTailUnblock = &nsHttpChannel::ConnectOnTailUnblock;
1487 return NS_OK;
1488 }
1489
1490 return ConnectOnTailUnblock();
1491}
1492
1493nsresult nsHttpChannel::ConnectOnTailUnblock() {
1494 nsresult rv;
1495
1496 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)
;
1497 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ConnectOnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject1498( "nsHttpChannel::ConnectOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
1498 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject1498( "nsHttpChannel::ConnectOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
1499
1500 // Consider opening a TCP connection right away.
1501 SpeculativeConnect();
1502
1503 // open a cache entry for this channel...
1504 rv = OpenCacheEntry(mURI->SchemeIs("https"));
1505
1506 // do not continue if asyncOpenCacheEntry is in progress
1507 if (AwaitingCacheCallbacks()) {
1508 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)
1509 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
1510 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"
, 1510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Unexpected state" ")"); do { MOZ_CrashSequence(__null
, 1510); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1511
1512 // Backstop against a wedged cache entry that never delivers its callback.
1513 MaybeStartCacheWaitTimer();
1514
1515 if (mNetworkTriggered && mWaitingForProxy) {
1516 // Someone has called TriggerNetwork(), meaning we are racing the
1517 // network with the cache.
1518 mWaitingForProxy = false;
1519 return ContinueConnect();
1520 }
1521
1522 return NS_OK;
1523 }
1524
1525 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1526 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)
1527 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)
;
1528 // if this channel is only allowed to pull from the cache, then
1529 // we must fail if we were unable to open a cache entry.
1530 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1531 return NS_ERROR_DOCUMENT_NOT_CACHED;
1532 }
1533 // otherwise, let's just proceed without using the cache.
1534 }
1535
1536 return TriggerNetwork();
1537}
1538
1539nsresult nsHttpChannel::ContinueConnect() {
1540 // If we need to start a CORS preflight, do it now!
1541 // Note that it is important to do this before the early returns below.
1542 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ContinueConnect", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject1543( "nsHttpChannel::ContinueConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
1543 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject1543( "nsHttpChannel::ContinueConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
1544 if (!LoadIsCorsPreflightDone() && LoadRequireCORSPreflight()) {
1545 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", 1545
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPreflightChannel"
")"); do { MOZ_CrashSequence(__null, 1545); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1546 nsresult rv = nsCORSListenerProxy::StartCORSPreflight(
1547 this, this, mUnsafeHeaders, getter_AddRefs(mPreflightChannel));
1548 return rv;
1549 }
1550
1551 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"
, 1553); 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, 1553); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1552 "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"
, 1553); 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, 1553); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1553 "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"
, 1553); 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, 1553); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1554
1555 bool forceOffline = IsForcedOffline();
1556
1557 // we may or may not have a cache entry at this point
1558 if (mCacheEntry) {
1559 // read straight from the cache if possible...
1560 if (CachedContentIsValid()) {
1561 // If we're forced offline, and set to bypass the cache, return offline.
1562 if (forceOffline &&
1563 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
1564 return NS_ERROR_OFFLINE;
1565 }
1566
1567 nsRunnableMethod<nsHttpChannel>* event = nullptr;
1568 nsresult rv;
1569 if (!LoadCachedContentIsPartial()) {
1570 rv = AsyncCall(&nsHttpChannel::AsyncOnExamineCachedResponse, &event);
1571 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1572 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)
;
1573 }
1574 }
1575 rv = ReadFromCache();
1576 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && event) {
1577 event->Revoke();
1578 }
1579
1580 AccumulateCacheHitTelemetry(kCacheHit, this);
1581 mCacheDisposition = kCacheHit;
1582
1583 return rv;
1584 }
1585 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1586 // the cache contains the requested resource, but it must be
1587 // validated before we can reuse it. since we are not allowed
1588 // to hit the net, there's nothing more to do. the document
1589 // is effectively not in the cache.
1590 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)
;
1591 return NS_ERROR_DOCUMENT_NOT_CACHED;
1592 }
1593 } else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1594 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)
;
1595 return NS_ERROR_DOCUMENT_NOT_CACHED;
1596 }
1597
1598 if (mLoadFlags & LOAD_NO_NETWORK_IO) {
1599 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)
;
1600 return NS_ERROR_DOCUMENT_NOT_CACHED;
1601 }
1602
1603 // We're about to hit the network. Don't if we're forced offline.
1604 if (forceOffline) {
1605 return NS_ERROR_OFFLINE;
1606 }
1607
1608 // hit the net...
1609 nsresult rv = DoConnect(mTransactionSticky);
1610 mTransactionSticky = nullptr;
1611 return rv;
1612}
1613
1614nsresult nsHttpChannel::DoConnect(HttpTransactionShell* aTransWithStickyConn) {
1615 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
)
;
1616
1617 if (!mDNSBlockingPromise.IsEmpty()) {
1618 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)
;
1619
1620 // Transaction is passed only from auth retry for which we will definitely
1621 // not block on DNS to alter the origin server name for IP; it has already
1622 // been done.
1623 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", 1623
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTransWithStickyConn"
")"); do { MOZ_CrashSequence(__null, 1623); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1624 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", 1624
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDNSBlockingThenable"
")"); do { MOZ_CrashSequence(__null, 1624); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1625
1626 nsCOMPtr<nsISerialEventTarget> target(do_GetMainThread());
1627 RefPtr<nsHttpChannel> self(this);
1628 mDNSBlockingThenable->Then(
1629 target, __func__,
1630 [self](const nsCOMPtr<nsIDNSRecord>& aRec) {
1631 nsresult rv = self->DoConnectActual(nullptr);
1632 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1633 self->CloseCacheEntry(false);
1634 (void)self->AsyncAbort(rv);
1635 }
1636 },
1637 [self](nsresult err) {
1638 self->CloseCacheEntry(false);
1639 (void)self->AsyncAbort(err);
1640 });
1641
1642 // The connection will continue when the promise is resolved in
1643 // OnLookupComplete.
1644 return NS_OK;
1645 }
1646
1647 return DoConnectActual(aTransWithStickyConn);
1648}
1649
1650nsresult nsHttpChannel::DoConnectActual(
1651 HttpTransactionShell* aTransWithStickyConn) {
1652 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)
1653 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)
;
1654
1655 nsresult rv = SetupChannelForTransaction();
1656 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1657 return rv;
1658 }
1659
1660 return CallOrWaitForResume(
1661 [trans = RefPtr(aTransWithStickyConn)](auto* self) {
1662 return self->DispatchTransaction(trans);
1663 });
1664}
1665
1666nsresult nsHttpChannel::DispatchTransaction(
1667 HttpTransactionShell* aTransWithStickyConn) {
1668 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)
1669 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)
;
1670 nsresult rv = InitTransaction();
1671 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1672 return rv;
1673 }
1674 if (aTransWithStickyConn) {
1675 rv = gHttpHandler->InitiateTransactionWithStickyConn(
1676 mTransaction, mPriority, aTransWithStickyConn);
1677 } else {
1678 rv = gHttpHandler->InitiateTransaction(mTransaction, mPriority);
1679 }
1680
1681 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1682 return rv;
1683 }
1684
1685 rv = mTransaction->AsyncRead(this, getter_AddRefs(mTransactionPump));
1686 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1687 // The transaction is already on the socket thread and points at our
1688 // request head; don't let it outlive us.
1689 (void)gHttpHandler->CancelTransaction(mTransaction, rv);
1690 return rv;
1691 }
1692
1693 uint32_t suspendCount = mSuspendCount;
1694 if (LoadAsyncResumePending()) {
1695 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)
1696 (" 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)
1697 ", 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)
1698 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)
;
1699 ++suspendCount;
1700 }
1701 while (suspendCount--) {
1702 mTransactionPump->Suspend();
1703 }
1704
1705 return NS_OK;
1706}
1707
1708void nsHttpChannel::SpeculativeConnect() {
1709 // Before we take the latency hit of dealing with the cache, try and
1710 // get the TCP (and SSL) handshakes going so they can overlap.
1711
1712 // don't speculate if we are offline, when doing http upgrade (i.e.
1713 // websockets bootstrap), or if we can't do keep-alive (because then we
1714 // couldn't reuse the speculative connection anyhow).
1715 if (gIOService->IsOffline() || mUpgradeProtocolCallback ||
1716 !(mCaps & NS_HTTP_ALLOW_KEEPALIVE(1 << 0)) || IsForcedOffline()) {
1717 return;
1718 }
1719
1720 // LOAD_ONLY_FROM_CACHE and LOAD_NO_NETWORK_IO must not hit network.
1721 // LOAD_FROM_CACHE is unlikely to hit network, so skip preconnects for it.
1722 if (mLoadFlags &
1723 (LOAD_ONLY_FROM_CACHE | LOAD_FROM_CACHE | LOAD_NO_NETWORK_IO)) {
1724 return;
1725 }
1726
1727 if (LoadAllowStaleCacheContent()) {
1728 return;
1729 }
1730
1731 nsCOMPtr<nsIInterfaceRequestor> callbacks;
1732 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
1733 getter_AddRefs(callbacks));
1734 if (!callbacks) return;
1735 // Disable HTTPS RR, since the new HappyEyeballs implementation will handle
1736 // it.
1737 bool httpsRRAllowed = !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) &&
1738 !(mCaps & NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30));
1739 (void)gHttpHandler->MaybeSpeculativeConnectWithHTTPSRR(
1740 mConnectionInfo, callbacks,
1741 mCaps & (NS_HTTP_DISALLOW_SPDY(1 << 7) | NS_HTTP_TRR_MODE_MASK((1 << 19) | (1 << 20)) |
1742 NS_HTTP_DISABLE_IPV4(1 << 17) | NS_HTTP_DISABLE_IPV6(1 << 18) |
1743 NS_HTTP_DISALLOW_HTTP3(1 << 21) | NS_HTTP_REFRESH_DNS(1 << 3)),
1744 nsHttpHandler::EchConfigEnabled() && httpsRRAllowed);
1745}
1746
1747void nsHttpChannel::DoNotifyListenerCleanup() {
1748 // We don't need this info anymore
1749 CleanRedirectCacheChainIfNecessary();
1750}
1751
1752void nsHttpChannel::ReleaseListeners() {
1753 HttpBaseChannel::ReleaseListeners();
1754
1755 mChannelClassifier = nullptr;
1756 mWarningReporter = nullptr;
1757 mEarlyHintObserver = nullptr;
1758 mWebTransportSessionEventListener = nullptr;
1759
1760 for (StreamFilterRequest& request : mStreamFilterRequests) {
1761 request.mPromise->Reject(false, __func__);
1762 }
1763 mStreamFilterRequests.Clear();
1764}
1765
1766void nsHttpChannel::DoAsyncAbort(nsresult aStatus) {
1767 (void)AsyncAbort(aStatus);
1768}
1769
1770void nsHttpChannel::HandleAsyncRedirect() {
1771 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"
, 1771); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 1771); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1772
1773 if (mSuspendCount) {
1774 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)
;
1775 mCallOnResume = [](nsHttpChannel* self) {
1776 self->HandleAsyncRedirect();
1777 return NS_OK;
1778 };
1779 return;
1780 }
1781
1782 nsresult rv = NS_OK;
1783
1784 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)
;
1785
1786 // since this event is handled asynchronously, it is possible that this
1787 // channel could have been canceled, in which case there would be no point
1788 // in processing the redirect.
1789 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) {
1790 PushRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1791 rv = AsyncProcessRedirection(mResponseHead->Status());
1792 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1793 PopRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1794 // TODO: if !DoNotRender3xxBody(), render redirect body instead.
1795 // But first we need to cache 3xx bodies (bug 748510)
1796 rv = ContinueHandleAsyncRedirect(rv);
1797 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"
, 1797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1797); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1798 }
1799 } else {
1800 rv = ContinueHandleAsyncRedirect(mStatus);
1801 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"
, 1801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1801); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1802 }
1803}
1804
1805nsresult nsHttpChannel::ContinueHandleAsyncRedirect(nsresult rv) {
1806 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1807 // If AsyncProcessRedirection fails, then we have to send out the
1808 // OnStart/OnStop notifications.
1809 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)
1810 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)
;
1811
1812 bool redirectsEnabled = !mLoadInfo->GetDontFollowRedirects();
1813
1814 if (redirectsEnabled) {
1815 // TODO: stop failing original channel if redirect vetoed?
1816 mStatus = rv;
1817
1818 DoNotifyListener();
1819
1820 // Blow away cache entry if we couldn't process the redirect
1821 // for some reason (the cache entry might be corrupt).
1822 if (mCacheEntry) {
1823 mCacheEntry->AsyncDoom(nullptr);
1824 }
1825 } else {
1826 DoNotifyListener();
1827 }
1828 }
1829
1830 CloseCacheEntry(true);
1831
1832 StoreIsPending(false);
1833
1834 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1835
1836 return NS_OK;
1837}
1838
1839void nsHttpChannel::HandleAsyncNotModified() {
1840 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"
, 1840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 1840); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1841
1842 if (mSuspendCount) {
1843 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)
;
1844 mCallOnResume = [](nsHttpChannel* self) {
1845 self->HandleAsyncNotModified();
1846 return NS_OK;
1847 };
1848 return;
1849 }
1850
1851 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)
;
1852
1853 DoNotifyListener();
1854
1855 CloseCacheEntry(false);
1856
1857 StoreIsPending(false);
1858
1859 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1860}
1861
1862nsresult nsHttpChannel::SetupChannelForTransaction() {
1863 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)
1864 "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)
1865 "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)
1866 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)
;
1867
1868 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"
, 1868); return NS_ERROR_ALREADY_INITIALIZED; } } while (false
)
;
1869
1870 nsresult rv;
1871
1872 if (StaticPrefs::network_http_priority_header_enabled()) {
1873 SetPriorityHeader();
1874 }
1875
1876 StoreUsedNetwork(1);
1877
1878 if (!LoadAllowSpdy()) {
1879 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
1880 }
1881 if (!LoadAllowHttp3()) {
1882 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
1883 }
1884 if (LoadBeConservative()) {
1885 mCaps |= NS_HTTP_BE_CONSERVATIVE(1 << 11);
1886 }
1887
1888 if (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) {
1889 mCaps |= NS_HTTP_LOAD_ANONYMOUS_CONNECT_ALLOW_CLIENT_CERT(1 << 23);
1890 }
1891
1892 if (nsContentUtils::ShouldResistFingerprinting(this,
1893 RFPTarget::HttpUserAgent)) {
1894 mCaps |= NS_HTTP_USE_RFP(1 << 26);
1895 }
1896
1897 // Use the URI path if not proxying (transparent proxying such as proxy
1898 // CONNECT does not count here). Also figure out what HTTP version to use.
1899 nsAutoCString buf, path;
1900 nsCString* requestURI;
1901
1902 // This is the normal e2e H1 path syntax "/index.html"
1903 rv = mURI->GetPathQueryRef(path);
1904 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1905 return rv;
1906 }
1907
1908 // path may contain UTF-8 characters, so ensure that they're escaped.
1909 if (NS_EscapeURL(path.get(), path.Length(), esc_OnlyNonASCII | esc_Spaces,
1910 buf)) {
1911 requestURI = &buf;
1912 } else {
1913 requestURI = &path;
1914 }
1915
1916 // trim off the #ref portion if any...
1917 int32_t ref1 = requestURI->FindChar('#');
1918 if (ref1 != kNotFound) {
1919 requestURI->SetLength(ref1);
1920 }
1921
1922 if (mConnectionInfo->UsingConnect() || !mConnectionInfo->UsingHttpProxy()) {
1923 mRequestHead.SetVersion(gHttpHandler->HttpVersion());
1924 } else {
1925 mRequestHead.SetPath(*requestURI);
1926
1927 // RequestURI should be the absolute uri H1 proxy syntax
1928 // "http://foo/index.html" so we will overwrite the relative version in
1929 // requestURI
1930 rv = mURI->GetUserPass(buf);
1931 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1932 if (!buf.IsEmpty() && ((strncmp(mSpec.get(), "http:", 5) == 0) ||
1933 strncmp(mSpec.get(), "https:", 6) == 0)) {
1934 nsCOMPtr<nsIURI> tempURI = nsIOService::CreateExposableURI(mURI);
1935 rv = tempURI->GetAsciiSpec(path);
1936 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1937 requestURI = &path;
1938 } else {
1939 requestURI = &mSpec;
1940 }
1941
1942 // trim off the #ref portion if any...
1943 int32_t ref2 = requestURI->FindChar('#');
1944 if (ref2 != kNotFound) {
1945 requestURI->SetLength(ref2);
1946 }
1947
1948 mRequestHead.SetVersion(gHttpHandler->ProxyHttpVersion());
1949 }
1950
1951 mRequestHead.SetRequestURI(*requestURI);
1952
1953 // set the request time for cache expiration calculations
1954 mRequestTime = NowInSeconds()PRTimeToSeconds(PR_Now());
1955 StoreRequestTimeInitialized(true);
1956
1957 // if doing a reload, force end-to-end
1958 if (mLoadFlags & LOAD_BYPASS_CACHE) {
1959 // We need to send 'Pragma:no-cache' to inhibit proxy caching even if
1960 // no proxy is configured since we might be talking with a transparent
1961 // proxy, i.e. one that operates at the network level. See bug #14772.
1962 // But we should not touch Pragma if Cache-Control is already set
1963 // (https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A3)
1964 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1965 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "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 // If we're configured to speak HTTP/1.1 then also send 'Cache-control:
1969 // no-cache'. But likewise don't touch Cache-Control if it's already set.
1970 if (mRequestHead.Version() >= HttpVersion::v1_1 &&
1971 !mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1972 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "no-cache", true);
1973 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"
, 1973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1973); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1974 }
1975 } else if (mLoadFlags & VALIDATE_ALWAYS) {
1976 // We need to send 'Cache-Control: max-age=0' to force each cache along
1977 // the path to the origin server to revalidate its own entry, if any,
1978 // with the next cache or server. See bug #84847.
1979 //
1980 // If we're configured to speak HTTP/1.0 then just send 'Pragma: no-cache'
1981 //
1982 // But don't send the headers if they're already set:
1983 // https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A2
1984 if (mRequestHead.Version() >= HttpVersion::v1_1) {
1985 if (!mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1986 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "max-age=0",
1987 true);
1988 }
1989 } else {
1990 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1991 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
1992 }
1993 }
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
1997 if (LoadResuming()) {
1998 char byteRange[32];
1999 SprintfLiteral(byteRange, "bytes=%" PRIu64"l" "u" "-", mStartPos);
2000 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(byteRange));
2001 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"
, 2001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2001); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2002
2003 if (!mEntityID.IsEmpty()) {
2004 // Also, we want an error if this resource changed in the meantime
2005 // Format of the entity id is: escaped_etag/size/lastmod
2006 nsCString::const_iterator start, end, slash;
2007 mEntityID.BeginReading(start);
2008 mEntityID.EndReading(end);
2009 mEntityID.BeginReading(slash);
2010
2011 if (FindCharInReadable('/', slash, end)) {
2012 nsAutoCString ifMatch;
2013 rv = mRequestHead.SetHeader(
2014 nsHttp::If_Match,
2015 NS_UnescapeURL(Substring(start, slash), 0, ifMatch));
2016 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2016); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2017
2018 ++slash; // Incrementing, so that searching for '/' won't find
2019 // the same slash again
2020 }
2021
2022 if (FindCharInReadable('/', slash, end)) {
2023 rv = mRequestHead.SetHeader(nsHttp::If_Unmodified_Since,
2024 Substring(++slash, end));
2025 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"
, 2025); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2025); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2026 }
2027 }
2028 }
2029
2030 // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
2031 if (mLoadFlags & LOAD_ANONYMOUS) mCaps |= NS_HTTP_LOAD_ANONYMOUS(1 << 4);
2032
2033 if (mUpgradeProtocolCallback) {
2034 rv = mRequestHead.SetHeader(nsHttp::Upgrade, mUpgradeProtocol, false);
2035 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"
, 2035); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2035); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2036 rv = mRequestHead.SetHeaderOnce(nsHttp::Connection, nsHttp::Upgrade.get(),
2037 false);
2038 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"
, 2038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2038); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2039 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
2040 mCaps &= ~NS_HTTP_ALLOW_KEEPALIVE(1 << 0);
2041 }
2042
2043 if (mWebTransportSessionEventListener) {
2044 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
2045 }
2046
2047 return NS_OK;
2048}
2049
2050// Updates mLNAPermission members based on existing permission and tracking
2051// flags in load info
2052LNAPermission nsHttpChannel::UpdateLocalNetworkAccessPermissions(
2053 const nsACString& aPermissionType) {
2054 // We should arrive at this point after LNA has been detected at the
2055 // transaction layer and has errored
2056
2057 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", 2058
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
")"); do { MOZ_CrashSequence(__null, 2058); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2058 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", 2058
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
")"); do { MOZ_CrashSequence(__null, 2058); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2059 LNAPermission userPerms = aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY
2060 ? mLNAPermission.mLocalHostPermission
2061 : mLNAPermission.mLocalNetworkPermission;
2062
2063 if (NS_WARN_IF(userPerms != LNAPermission::Pending)NS_warn_if_impl(userPerms != LNAPermission::Pending, "userPerms != LNAPermission::Pending"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2063
)
) {
2064 // Unexpected condition, we should not hit this case
2065 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"
, 2067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2067); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2066 "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"
, 2067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2067); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2067 "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"
, 2067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2067); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
2068 return userPerms;
2069 }
2070
2071 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"
, 2071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->TriggeringPrincipal()"
") (" "need triggering principal" ")"); do { MOZ_CrashSequence
(__null, 2071); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2072
2073 // Skip LNA checks if the triggering principal and target are same origin.
2074 // Note: This could be a case where there is a network change or device
2075 // migration to a private or corporate network.
2076 //
2077 // This only holds when we connect directly to the origin's own endpoint. If
2078 // the connection was rerouted via Alt-Svc to a different host/port, a
2079 // same-origin URL no longer implies we are talking to the origin itself: a
2080 // public origin could steer same-origin traffic to an attacker-selected
2081 // private address. Don't grant the exemption in that case.
2082 bool reroutedElsewhere =
2083 mConnectionInfo && !mConnectionInfo->GetRoutedHost().IsEmpty() &&
2084 (!mConnectionInfo->GetRoutedHost().Equals(mConnectionInfo->GetOrigin()) ||
2085 mConnectionInfo->RoutedPort() != mConnectionInfo->OriginPort());
2086 // This exemption (same origin) should apply only to secure contexts.
2087 const bool triggeringPrincipalIsPotentiallyTrustworthy =
2088 mLoadInfo->TriggeringPrincipal()->GetIsOriginPotentiallyTrustworthy();
2089 bool isSameOrigin = false;
2090 nsresult rv =
2091 mLoadInfo->TriggeringPrincipal()->IsSameOrigin(mURI, &isSameOrigin);
2092 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && isSameOrigin && !reroutedElsewhere &&
2093 triggeringPrincipalIsPotentiallyTrustworthy) {
2094 userPerms = LNAPermission::Granted;
2095 return userPerms;
2096 }
2097
2098 // Skip LNA checks if captive portal is active
2099 nsCOMPtr<nsICaptivePortalService> cps = CaptivePortalService::GetSingleton();
2100 if (cps) {
2101 int32_t state = cps->State();
2102 if (state == nsICaptivePortalService::LOCKED_PORTAL &&
2103 aPermissionType == LOCAL_NETWORK_PERMISSION_KEY) {
2104 userPerms = LNAPermission::Granted;
2105 return userPerms;
2106 }
2107 }
2108
2109 // Step 1. Check for Existing Allow or Deny permission
2110 if (nsContentUtils::IsExactSitePermAllow(mLoadInfo->TriggeringPrincipal(),
2111 aPermissionType)) {
2112 userPerms = LNAPermission::Granted;
2113 return userPerms;
2114 }
2115
2116 if (nsContentUtils::IsExactSitePermDeny(mLoadInfo->TriggeringPrincipal(),
2117 aPermissionType)) {
2118 userPerms = LNAPermission::Denied;
2119 return userPerms;
2120 }
2121
2122 // Step 2.If this is from third Party Tracker, just block
2123 uint32_t flags = 0;
2124 using CF = nsIClassifiedChannel::ClassificationFlags;
2125 if (StaticPrefs::network_lna_block_trackers() &&
2126 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
2127 mLoadInfo->GetTriggeringThirdPartyClassificationFlags(&flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
&&
2128 (flags & (CF::CLASSIFIED_ANY_BASIC_TRACKING |
2129 CF::CLASSIFIED_ANY_SOCIAL_TRACKING)) != 0) {
2130 userPerms = LNAPermission::Denied;
2131 return userPerms;
2132 }
2133
2134 // Check if we should block LNA requests from insecure contexts
2135 if (StaticPrefs::network_lna_block_insecure_contexts() &&
2136 !triggeringPrincipalIsPotentiallyTrustworthy) {
2137 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)
2138 ("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)
2139 "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)
2140 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
2141 userPerms = LNAPermission::Denied;
2142 return userPerms;
2143 }
2144
2145 // Step 3
2146 // could not determine the permission, lets prompt user
2147 // for permission if lna blocking is enabled
2148 if (StaticPrefs::network_lna_blocking()) {
2149 return userPerms;
2150 }
2151
2152 // we dont have reasons to block the request so we allow this LNA request
2153 // Ideally we should not hit this case once the feature is fully shipped
2154 userPerms = LNAPermission::Granted;
2155 return userPerms;
2156}
2157
2158nsresult nsHttpChannel::InitTransaction() {
2159 nsresult rv;
2160 // create wrapper for this channel's notification callbacks
2161 nsCOMPtr<nsIInterfaceRequestor> callbacks;
2162 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
2163 getter_AddRefs(callbacks));
2164
2165 // create the transaction object
2166 if (nsIOService::UseSocketProcess()) {
2167 if (NS_WARN_IF(!gIOService->SocketProcessReady())NS_warn_if_impl(!gIOService->SocketProcessReady(), "!gIOService->SocketProcessReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2167
)
) {
2168 return NS_ERROR_NOT_AVAILABLE;
2169 }
2170 RefPtr<SocketProcessParent> socketProcess =
2171 SocketProcessParent::GetSingleton();
2172 if (!socketProcess->CanSend()) {
2173 return NS_ERROR_NOT_AVAILABLE;
2174 }
2175
2176 nsCOMPtr<nsIParentChannel> parentChannel;
2177 NS_QueryNotificationCallbacks(this, parentChannel);
2178 RefPtr<DocumentLoadListener> documentChannelParent =
2179 do_QueryObject(parentChannel);
2180 // See HttpTransactionChild::CanSendODAToContentProcessDirectly() and
2181 // nsHttpChannel::CallOnStartRequest() for the reason why we need to know if
2182 // this is a document load. We only send ODA directly to child process for
2183 // non document loads.
2184 RefPtr<HttpTransactionParent> transParent =
2185 new HttpTransactionParent(!!documentChannelParent);
2186 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)
2187 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)
;
2188
2189 // Since OnStopRequest could be sent to child process from socket process
2190 // directly, we need to store these two values in HttpTransactionChild and
2191 // forward to child process until HttpTransactionChild::OnStopRequest is
2192 // called.
2193 transParent->SetRedirectTimestamp(mRedirectStartTimeStamp,
2194 mRedirectEndTimeStamp);
2195
2196 if (socketProcess) {
2197 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", 2198
); AnnotateMozCrashReason("MOZ_CRASH(" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")"); do { MOZ_CrashSequence(__null, 2198); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
2198 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", 2198
); AnnotateMozCrashReason("MOZ_CRASH(" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")"); do { MOZ_CrashSequence(__null, 2198); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2199 }
2200 mTransaction = transParent;
2201 } else {
2202 mTransaction = new nsHttpTransaction();
2203 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)
2204 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)
;
2205 }
2206
2207 // Save the mapping of channel id and the channel. We need this mapping for
2208 // nsIHttpActivityObserver.
2209 gHttpHandler->AddHttpChannel(mChannelId, ToSupports(this));
2210
2211 EnsureBrowserId();
2212 EnsureRequestContext();
2213
2214 HttpTrafficCategory category = CreateTrafficCategory();
2215 mTransaction->SetIsForWebTransport(!!mWebTransportSessionEventListener);
2216 mTransaction->SetRequestBodyIsStreaming(LoadUploadStreamIsStreaming());
2217
2218 RefPtr<mozilla::dom::BrowsingContext> bc;
2219 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
2220
2221 nsILoadInfo::IPAddressSpace parentAddressSpace =
2222 mozilla::net::GetParentIPAddressSpace(mLoadInfo);
2223
2224 // Check if this is a top-level navigation load and grant LNA permissions
2225 // to skip local network access verification for navigational loads
2226 if (mLoadInfo && StaticPrefs::network_lna_allow_top_level_navigation()) {
2227 ExtContentPolicyType contentPolicyType =
2228 mLoadInfo->GetExternalContentPolicyType();
2229 if (contentPolicyType == ExtContentPolicy::TYPE_DOCUMENT) {
2230 // Grant permissions for top-level navigation loads
2231 mLNAPermission.mLocalHostPermission = LNAPermission::Granted;
2232 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
2233 }
2234 }
2235
2236 // Grant LNA permissions for captive portal tabs to allow them to access
2237 // local network resources without prompting the user
2238 if (bc && bc->GetIsCaptivePortalTab()) {
2239 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
2240 }
2241
2242 rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead, mUploadStream,
2243 mReqContentLength, GetCurrentSerialEventTarget(),
2244 callbacks, this, mBrowserId, category,
2245 mRequestContext, mClassOfService, mInitialRwin,
2246 LoadResponseTimeoutEnabled(), mChannelId, nullptr,
2247 parentAddressSpace, mLNAPermission);
2248 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2249 mTransaction = nullptr;
2250 return rv;
2251 }
2252
2253 return rv;
2254}
2255
2256HttpTrafficCategory nsHttpChannel::CreateTrafficCategory() {
2257 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", 2258
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 2258); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2258 !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", 2258
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 2258); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2259
2260 if (!StaticPrefs::network_traffic_analyzer_enabled()) {
2261 return HttpTrafficCategory::eInvalid;
2262 }
2263
2264 HttpTrafficAnalyzer::ClassOfService cos;
2265 {
2266 if ((mClassOfService.Flags() & nsIClassOfService::Leader) &&
2267 mLoadInfo->GetExternalContentPolicyType() ==
2268 ExtContentPolicy::TYPE_SCRIPT) {
2269 cos = HttpTrafficAnalyzer::ClassOfService::eLeader;
2270 } else if (mLoadFlags & nsIRequest::LOAD_BACKGROUND) {
2271 cos = HttpTrafficAnalyzer::ClassOfService::eBackground;
2272 } else {
2273 cos = HttpTrafficAnalyzer::ClassOfService::eOther;
2274 }
2275 }
2276
2277 bool isThirdParty = AntiTrackingUtils::IsThirdPartyChannel(this);
2278
2279 HttpTrafficAnalyzer::TrackingClassification tc;
2280 {
2281 uint32_t flags = isThirdParty ? mThirdPartyClassificationFlags
2282 : mFirstPartyClassificationFlags;
2283
2284 using CF = nsIClassifiedChannel::ClassificationFlags;
2285 using TC = HttpTrafficAnalyzer::TrackingClassification;
2286
2287 if (flags & CF::CLASSIFIED_TRACKING_CONTENT) {
2288 tc = TC::eContent;
2289 } else if (flags & CF::CLASSIFIED_FINGERPRINTING_CONTENT) {
2290 tc = TC::eFingerprinting;
2291 } else if (flags & CF::CLASSIFIED_ANY_BASIC_TRACKING) {
2292 tc = TC::eBasic;
2293 } else {
2294 tc = TC::eNone;
2295 }
2296 }
2297
2298 bool isSystemPrincipal =
2299 mLoadInfo->GetLoadingPrincipal() &&
2300 mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal();
2301 return HttpTrafficAnalyzer::CreateTrafficCategory(
2302 NS_UsePrivateBrowsing(this), isSystemPrincipal, isThirdParty, cos, tc);
2303}
2304
2305void nsHttpChannel::SetCachedContentType() {
2306 if (!mResponseHead) {
2307 return;
2308 }
2309
2310 nsAutoCString contentTypeStr;
2311 mResponseHead->ContentType(contentTypeStr);
2312
2313 uint8_t contentType = nsICacheEntry::CONTENT_TYPE_OTHER;
2314 if (nsContentUtils::IsJavascriptMIMEType(
2315 NS_ConvertUTF8toUTF16(contentTypeStr))) {
2316 contentType = nsICacheEntry::CONTENT_TYPE_JAVASCRIPT;
2317 } else if (StringBeginsWith(contentTypeStr, "text/css"_ns) ||
2318 (mLoadInfo->GetExternalContentPolicyType() ==
2319 ExtContentPolicy::TYPE_STYLESHEET)) {
2320 contentType = nsICacheEntry::CONTENT_TYPE_STYLESHEET;
2321 } else if (StringBeginsWith(contentTypeStr, "application/wasm"_ns)) {
2322 contentType = nsICacheEntry::CONTENT_TYPE_WASM;
2323 } else if (StringBeginsWith(contentTypeStr, "image/"_ns)) {
2324 contentType = nsICacheEntry::CONTENT_TYPE_IMAGE;
2325 } else if (StringBeginsWith(contentTypeStr, "video/"_ns)) {
2326 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
2327 } else if (StringBeginsWith(contentTypeStr, "audio/"_ns)) {
2328 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
2329 }
2330
2331 mCacheEntry->SetContentType(contentType);
2332}
2333
2334static bool ShouldSniffMisconfiguredType(nsHttpResponseHead* aResponseHead,
2335 nsILoadInfo* aLoadInfo) {
2336 if (!StaticPrefs::network_mimesniff_sniff_misconfigured_types()) {
2337 return false;
2338 }
2339
2340 // Only sniff document navigations, not subresources.
2341 // https://mimesniff.spec.whatwg.org/#sniffing-a-mislabeled-binary-resource
2342 auto type = aLoadInfo->GetExternalContentPolicyType();
2343 if (type != ExtContentPolicyType::TYPE_DOCUMENT &&
2344 type != ExtContentPolicyType::TYPE_SUBDOCUMENT) {
2345 return false;
2346 }
2347
2348 // Responses marked as attachments are already going to be downloaded
2349 // regardless of their content type, so there is no need to sniff them.
2350 nsAutoCString contentDisposition;
2351 if (NS_SUCCEEDED(aResponseHead->GetHeader(nsHttp::Content_Disposition,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Content_Disposition, contentDisposition))),
1)))
2352 contentDisposition))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Content_Disposition, contentDisposition))),
1)))
&&
2353 !contentDisposition.IsEmpty() &&
2354 NS_GetContentDispositionFromHeader(contentDisposition) ==
2355 nsIChannel::DISPOSITION_ATTACHMENT) {
2356 return false;
2357 }
2358
2359 nsAutoCString contentTypeOptionsHeader;
2360 if (aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader) &&
2361 contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) {
2362 return false;
2363 }
2364
2365 nsAutoCString contentType;
2366 aResponseHead->ContentType(contentType);
2367
2368 if (contentType.EqualsLiteral("text/plain")) {
2369 return true;
2370 }
2371
2372 if (contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type") ||
2373 contentType.IsEmpty()) {
2374 return true;
2375 }
2376
2377 return false;
2378}
2379
2380nsresult nsHttpChannel::CallOnStartRequest() {
2381 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)
;
2382
2383 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"
, 2385); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2385
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2384 "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"
, 2385); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2385
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2385 "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"
, 2385); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2385
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
2386
2387 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"
, 2389); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2389); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
2388 "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"
, 2389); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2389); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
2389 "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"
, 2389); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2389); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
2390
2391 mEarlyHintObserver = nullptr;
2392
2393 if (StaticPrefs::network_http_network_error_logging_enabled() &&
2394 mResponseHead && mResponseHead->HasHeader(nsHttp::NEL) &&
2395 LoadUsedNetwork()) {
2396 // If the policy gets cleared, but this response is still in the cache,
2397 // we probably don't want to reinstall the policy when the entry is
2398 // reloaded. That means it's important to only call RegisterPolicy when
2399 // LoadUsedNetwork() is true.
2400 if (nsCOMPtr<nsINetworkErrorLogging> nel =
2401 components::NetworkErrorLogging::Service()) {
2402 nel->RegisterPolicy(this);
2403 }
2404 }
2405
2406 if (LoadOnStartRequestCalled()) {
2407 // This can only happen when a range request loading rest of the data
2408 // after interrupted concurrent cache read asynchronously failed, e.g.
2409 // the response range bytes are not as expected or this channel has
2410 // been externally canceled.
2411 //
2412 // It's legal to bypass CallOnStartRequest for that case since we've
2413 // already called OnStartRequest on our listener and also added all
2414 // content converters before.
2415 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", 2415
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { MOZ_CrashSequence(__null, 2415); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2416 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)
;
2417 return mStatus;
2418 }
2419
2420 // Ensure mListener->OnStartRequest will be invoked before exiting
2421 // this function.
2422 auto onStartGuard = MakeScopeExit([&] {
2423 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)
2424 (" 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)
2425 "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)
2426 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)
;
2427 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", 2427
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 2427); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2428
2429 if (mListener) {
2430 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
2431 StoreOnStartRequestCalled(true);
2432 deleteProtector->OnStartRequest(this);
2433 }
2434 StoreOnStartRequestCalled(true);
2435 });
2436
2437 nsresult rv = ValidateMIMEType();
2438 // Since ODA and OnStopRequest could be sent from socket process directly, we
2439 // need to update the channel status before calling mListener->OnStartRequest.
2440 // This is the only way to let child process discard the already received ODA
2441 // messages.
2442 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2443 mStatus = rv;
2444 return mStatus;
2445 }
2446
2447 // EnsureOpaqueResponseIsAllowed and EnsureOpauqeResponseIsAllowedAfterSniff
2448 // are the checks for Opaque Response Blocking to ensure that we block as many
2449 // cross-origin responses with CORS headers as possible that are not either
2450 // Javascript or media to avoid leaking their contents through side channels.
2451 OpaqueResponse opaqueResponse =
2452 PerformOpaqueResponseSafelistCheckBeforeSniff();
2453 if (opaqueResponse == OpaqueResponse::Block) {
2454 SetChannelBlockedByOpaqueResponse();
2455 CancelWithReason(NS_ERROR_DOM_NETWORK_ERR,
2456 "OpaqueResponseBlocker::BlockResponse"_ns);
2457 return NS_BINDING_ABORTED;
2458 }
2459
2460 // We must ensure that any dcb/dcz content is decompressed in the parent
2461 // process, and removed from the Content-Encoding before it's sent down
2462 // to the content process. In most (all?) cases, this should have occurred
2463 // before this.
2464 if (mResponseHead && XRE_IsParentProcess() && !LoadHasAppliedConversion()) {
2465 nsAutoCString contentEncoding;
2466 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
2467 // Note: doesn't handle multiple compressors: "dcb, gzip" or
2468 // "gzip, dcb" (etc)
2469 if (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
2470 contentEncoding.LowerCaseEqualsLiteral("dcz")) {
2471 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)
2472 ("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)
2473 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)
;
2474 nsCOMPtr<nsIStreamListener> listener;
2475 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"
, 2475); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "LoadHasAppliedConversion() == false"
")"); do { MOZ_CrashSequence(__null, 2475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2476 // Insist we install a converter. This should never be the case, but
2477 // if somehow it is, we need a converter; content can't be allowed
2478 // to see dcb/dcz since it can't convert them
2479 StoreHasAppliedConversion(false);
2480 // IMPORTANT: Must use DoApplyContentConversionsInternal with
2481 // aRemoveEncodings=true to clear Content-Encoding header. Otherwise,
2482 // decompressed data will be cached with dcb/dcz in metadata, causing
2483 // corruption on cache reads.
2484 rv = DoApplyContentConversionsInternal(
2485 mListener, getter_AddRefs(listener), true, nullptr);
2486 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2487 return rv;
2488 }
2489 if (listener) {
2490 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"
, 2493); 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, 2493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2491 "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"
, 2493); 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, 2493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2492 "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"
, 2493); 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, 2493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2493 "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"
, 2493); 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, 2493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2494 mListener = listener;
2495 mCompressListener = listener;
2496
2497 StoreHasAppliedConversion(true);
2498 } else {
2499 // Failed to install decompressor for dcb/dcz - this is a fatal error
2500 // as content cannot handle these encodings
2501 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)
2502 ("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)
2503 "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)
2504 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)
;
2505 return NS_ERROR_INVALID_CONTENT_ENCODING;
2506 }
2507 }
2508 }
2509
2510 // Allow consumers to override our content type
2511 if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) {
2512 // NOTE: We can have both a txn pump and a cache pump when the cache
2513 // content is partial. In that case, we need to read from the cache,
2514 // because that's the one that has the initial contents. If that fails
2515 // then give the transaction pump a shot.
2516
2517 nsIChannel* thisChannel = static_cast<nsIChannel*>(this);
2518
2519 bool typeSniffersCalled = false;
2520 if (mCachePump) {
2521 typeSniffersCalled =
2522 NS_SUCCEEDED(mCachePump->PeekStream(CallTypeSniffers, thisChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCachePump->PeekStream
(CallTypeSniffers, thisChannel))), 1)))
;
2523 }
2524
2525 if (!typeSniffersCalled && mTransactionPump) {
2526 RefPtr<nsInputStreamPump> pump = do_QueryObject(mTransactionPump);
2527 if (pump) {
2528 pump->PeekStream(CallTypeSniffers, thisChannel);
2529 } else {
2530 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"
, 2530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsIOService::UseSocketProcess()"
")"); do { MOZ_CrashSequence(__null, 2530); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2531 RefPtr<HttpTransactionParent> trans = do_QueryObject(mTransactionPump);
2532 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"
, 2532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "trans" ")")
; do { MOZ_CrashSequence(__null, 2532); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2533 trans->SetSniffedTypeToChannel(CallTypeSniffers, thisChannel);
2534 }
2535 }
2536 }
2537
2538 // Note that the code below should be synced with the code in
2539 // HttpTransactionChild::CanSendODAToContentProcessDirectly(). We MUST make
2540 // sure HttpTransactionChild::CanSendODAToContentProcessDirectly() returns
2541 // false when a stream converter is applied.
2542 bool unknownDecoderStarted = false;
2543 bool shouldSniff = false;
2544 if (mResponseHead) {
2545 if (!mResponseHead->HasContentType()) {
2546 shouldSniff = true;
2547 } else {
2548 shouldSniff =
2549 ShouldSniffMisconfiguredType(mResponseHead.get(), mLoadInfo);
2550 }
2551 }
2552 if (shouldSniff) {
2553 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"
, 2553); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo"
") (" "Should have connection info here" ")"); do { MOZ_CrashSequence
(__null, 2553); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2554 if (!mContentTypeHint.IsEmpty()) {
2555 mResponseHead->SetContentType(mContentTypeHint);
2556 } else if (mResponseHead->Version() == HttpVersion::v0_9 &&
2557 mConnectionInfo->OriginPort() !=
2558 mConnectionInfo->DefaultPort()) {
2559 mResponseHead->SetContentType(nsLiteralCString(TEXT_PLAIN"text/plain"));
2560 } else if (!mLoadInfo->GetSkipContentSniffing() ||
2561 opaqueResponse == OpaqueResponse::Sniff) {
2562 // Uh-oh. We had better find out what type we are!
2563 mListener = new nsUnknownDecoder(mListener);
2564 unknownDecoderStarted = true;
2565 }
2566 }
2567
2568 // If unknownDecoder is not going to be launched, call
2569 // EnsureOpaqueResponseIsAllowedAfterSniff immediately.
2570 if (!unknownDecoderStarted) {
2571 if (opaqueResponse == OpaqueResponse::SniffCompressed) {
2572 mListener = new nsCompressedAudioVideoImageDetector(
2573 mListener, &HttpBaseChannel::CallTypeSniffers);
2574 } else if (opaqueResponse == OpaqueResponse::Sniff) {
2575 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"
, 2575); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mORB"
")"); do { MOZ_CrashSequence(__null, 2575); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2576 RefPtr<OpaqueResponseBlocker> orb(mORB);
2577 nsresult rv = orb->EnsureOpaqueResponseIsAllowedAfterSniff(this);
2578
2579 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2580 return rv;
2581 }
2582 }
2583 }
2584
2585 // If the content is multipart/x-mixed-replace, we'll insert a MIME decoder
2586 // in the pipeline to handle the content and pass it along to our
2587 // original listener. nsUnknownDecoder doesn't support detecting this type,
2588 // so we only need to insert this using the response header's mime type.
2589 //
2590 // We only do this for unwrapped document loads, since we might want to send
2591 // parts to the external protocol handler without leaving the parent process.
2592 bool mustRunStreamFilterInParent = false;
2593 nsCOMPtr<nsIParentChannel> parentChannel;
2594 NS_QueryNotificationCallbacks(this, parentChannel);
2595 RefPtr<DocumentLoadListener> docListener = do_QueryObject(parentChannel);
2596 if (mResponseHead && docListener && docListener->GetChannel() == this) {
2597 nsAutoCString contentType;
2598 mResponseHead->ContentType(contentType);
2599
2600 if (contentType.Equals("multipart/x-mixed-replace"_ns)) {
2601 nsCOMPtr<nsIStreamConverterService> convServ(
2602 mozilla::components::StreamConverter::Service(&rv));
2603 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2604 nsCOMPtr<nsIStreamListener> toListener(mListener);
2605 nsCOMPtr<nsIStreamListener> fromListener;
2606
2607 rv = convServ->AsyncConvertData("multipart/x-mixed-replace", "*/*",
2608 toListener, nullptr,
2609 getter_AddRefs(fromListener));
2610 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2611 mListener = fromListener;
2612 mustRunStreamFilterInParent = true;
2613 }
2614 }
2615 }
2616 }
2617
2618 // If we installed a multipart converter, then we need to add StreamFilter
2619 // object before it, so that extensions see the un-parsed original stream.
2620 // We may want to add an option for extensions to opt-in to proper multipart
2621 // handling.
2622 // If not, then pass the StreamFilter promise on to DocumentLoadListener,
2623 // where it'll be added in the content process.
2624 for (StreamFilterRequest& request : mStreamFilterRequests) {
2625 if (mustRunStreamFilterInParent) {
2626 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
2627 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
2628 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
2629 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2630 request.mPromise->Reject(false, __func__);
2631 } else {
2632 extensions::StreamFilterParent::Attach(this, std::move(parent));
2633 request.mPromise->Resolve(std::move(child), __func__);
2634 }
2635 } else {
2636 if (docListener) {
2637 docListener->AttachStreamFilter()->ChainTo(request.mPromise.forget(),
2638 __func__);
2639 } else {
2640 request.mPromise->Reject(false, __func__);
2641 }
2642 }
2643 request.mPromise = nullptr;
2644 }
2645 mStreamFilterRequests.Clear();
2646 StoreTracingEnabled(false);
2647
2648 if (mResponseHead && !mResponseHead->HasContentCharset()) {
2649 mResponseHead->SetContentCharset(mContentCharsetHint);
2650 }
2651
2652 if (mCacheEntry && LoadCacheEntryIsWriteOnly()) {
2653 SetCachedContentType();
2654 }
2655
2656 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)
2657 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)
;
2658
2659 // About to call OnStartRequest, dismiss the guard object.
2660 onStartGuard.release();
2661
2662 if (mListener) {
2663 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"
, 2664); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { MOZ_CrashSequence
(__null, 2664); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2664 "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"
, 2664); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { MOZ_CrashSequence
(__null, 2664); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2665 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
2666 StoreOnStartRequestCalled(true);
2667 rv = deleteProtector->OnStartRequest(this);
2668 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2669 } else {
2670 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"
, 2670)
;
2671 StoreOnStartRequestCalled(true);
2672 }
2673
2674 // Install stream converter if required.
2675 // Normally, we expect the listener to disable content conversion during
2676 // OnStartRequest if it wants to handle it itself (which is common case with
2677 // HttpChannelParent, disabling so that it can be done in the content
2678 // process). If we've installed an nsUnknownDecoder, then we won't yet have
2679 // called OnStartRequest on the final listener (that happens after we send
2680 // OnDataAvailable to the nsUnknownDecoder), so it can't yet have disabled
2681 // content conversion.
2682 // In that case, assume that the listener will disable content conversion,
2683 // unless it's specifically told us that it won't.
2684 if (!unknownDecoderStarted || LoadListenerRequiresContentConversion()) {
2685 nsCOMPtr<nsIStreamListener> listener;
2686 rv =
2687 DoApplyContentConversions(mListener, getter_AddRefs(listener), nullptr);
2688 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2689 return rv;
2690 }
2691 if (listener) {
2692 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"
, 2695); 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, 2695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2693 "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"
, 2695); 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, 2695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2694 "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"
, 2695); 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, 2695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2695 "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"
, 2695); 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, 2695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2696 mListener = listener;
2697 mCompressListener = std::move(listener);
2698
2699 StoreHasAppliedConversion(true);
2700 }
2701 }
2702
2703 // if this channel is for a download, close off access to the cache.
2704 if (mCacheEntry && LoadChannelIsForDownload()) {
2705 mCacheEntry->AsyncDoom(nullptr);
2706
2707 // We must keep the cache entry in case of partial request.
2708 // Concurrent access is the same, we need the entry in
2709 // OnStopRequest.
2710 if (!LoadCachedContentIsPartial() && !LoadConcurrentCacheAccess()) {
2711 CloseCacheEntry(false);
2712 }
2713 }
2714
2715 return NS_OK;
2716}
2717
2718NS_IMETHODIMPnsresult nsHttpChannel::GetHttpProxyConnectResponseCode(
2719 int32_t* aResponseCode) {
2720 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"
, 2720); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2721 if (mProxyConnectResponseHead) {
2722 *aResponseCode = mProxyConnectResponseHead->Head().Status();
2723 } else if (mConnectionInfo && mConnectionInfo->UsingConnect()) {
2724 *aResponseCode = 0;
2725 } else {
2726 *aResponseCode = -1;
2727 }
2728 return NS_OK;
2729}
2730
2731NS_IMETHODIMPnsresult nsHttpChannel::GetHttpProxyResponseHeader(
2732 const nsACString& aHeader, nsACString& aValue) {
2733 if (mProxyConnectResponseHead) {
2734 return mProxyConnectResponseHead->Head().GetHeader(
2735 nsHttp::ResolveAtom(aHeader), aValue);
2736 }
2737 return NS_ERROR_NOT_AVAILABLE;
2738}
2739
2740nsresult nsHttpChannel::ProcessFailedProxyConnect(uint32_t httpStatus) {
2741 // Failure to set up a proxy tunnel via CONNECT means one of the following:
2742 // 1) Proxy wants authorization, or forbids.
2743 // 2) DNS at proxy couldn't resolve target URL.
2744 // 3) Proxy connection to target failed or timed out.
2745 // 4) Eve intercepted our CONNECT, and is replying with malicious HTML.
2746 //
2747 // Our current architecture would parse the proxy's response content with
2748 // the permission of the target URL. Given #4, we must avoid rendering the
2749 // body of the reply, and instead give the user a (hopefully helpful)
2750 // boilerplate error page, based on just the HTTP status of the reply.
2751
2752 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"
, 2753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ MOZ_CrashSequence(__null, 2753); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2753 "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"
, 2753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ MOZ_CrashSequence(__null, 2753); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2754 nsresult rv = HttpProxyResponseToErrorCode(httpStatus);
2755 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)
2756 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)
;
2757
2758 // Make sure the connection is thrown away as it can be in a bad state
2759 // and the proxy may just hang on the next request.
2760 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"
, 2760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { MOZ_CrashSequence(__null, 2760); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2761 mTransaction->DontReuseConnection();
2762
2763 Cancel(rv);
2764 {
2765 nsresult rv = CallOnStartRequest();
2766 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2767 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)
2768 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)
;
2769 }
2770 }
2771 return rv;
2772}
2773
2774static void GetSTSConsoleErrorTag(uint32_t failureResult,
2775 nsAString& consoleErrorTag) {
2776 switch (failureResult) {
2777 case nsISiteSecurityService::ERROR_COULD_NOT_PARSE_HEADER:
2778 consoleErrorTag = u"STSCouldNotParseHeader"_ns;
2779 break;
2780 case nsISiteSecurityService::ERROR_NO_MAX_AGE:
2781 consoleErrorTag = u"STSNoMaxAge"_ns;
2782 break;
2783 case nsISiteSecurityService::ERROR_MULTIPLE_MAX_AGES:
2784 consoleErrorTag = u"STSMultipleMaxAges"_ns;
2785 break;
2786 case nsISiteSecurityService::ERROR_INVALID_MAX_AGE:
2787 consoleErrorTag = u"STSInvalidMaxAge"_ns;
2788 break;
2789 case nsISiteSecurityService::ERROR_MULTIPLE_INCLUDE_SUBDOMAINS:
2790 consoleErrorTag = u"STSMultipleIncludeSubdomains"_ns;
2791 break;
2792 case nsISiteSecurityService::ERROR_INVALID_INCLUDE_SUBDOMAINS:
2793 consoleErrorTag = u"STSInvalidIncludeSubdomains"_ns;
2794 break;
2795 case nsISiteSecurityService::ERROR_COULD_NOT_SAVE_STATE:
2796 consoleErrorTag = u"STSCouldNotSaveState"_ns;
2797 break;
2798 default:
2799 consoleErrorTag = u"STSUnknownError"_ns;
2800 break;
2801 }
2802}
2803
2804/**
2805 * Process an HTTP Strict Transport Security (HSTS) header.
2806 */
2807nsresult nsHttpChannel::ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo) {
2808 nsHttpAtom atom(nsHttp::ResolveAtom("Strict-Transport-Security"_ns));
2809
2810 nsAutoCString securityHeader;
2811 nsresult rv = mResponseHead->GetHeader(atom, securityHeader);
2812 if (rv == NS_ERROR_NOT_AVAILABLE) {
2813 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)
;
2814 return NS_OK;
2815 }
2816 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"
, 2816)
) {
2817 return rv;
2818 }
2819
2820 if (!aSecInfo) {
2821 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)
;
2822 return NS_ERROR_INVALID_ARG;
2823 }
2824 nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
2825 rv = aSecInfo->GetOverridableErrorCategory(&overridableErrorCategory);
2826 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"
, 2826)
) {
2827 return rv;
2828 }
2829 if (overridableErrorCategory !=
2830 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
2831 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessHSTSHeader: untrustworthy connection - not "
"processing header"); } } while (0)
2832 ("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)
2833 "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)
;
2834 return NS_ERROR_FAILURE;
2835 }
2836
2837 nsISiteSecurityService* sss = gHttpHandler->GetSSService();
2838 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"
, 2838); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2839
2840 OriginAttributes originAttributes;
2841 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2842
)
2842 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2842
)
) {
2843 return NS_ERROR_FAILURE;
2844 }
2845
2846 uint32_t failureResult;
2847 rv = sss->ProcessHeader(mURI, securityHeader, originAttributes, nullptr,
2848 nullptr, &failureResult);
2849 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2850 nsAutoString consoleErrorCategory(u"Invalid HSTS Headers"_ns);
2851 nsAutoString consoleErrorTag;
2852 GetSTSConsoleErrorTag(failureResult, consoleErrorTag);
2853 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2854 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)
2855 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)
;
2856 }
2857 return NS_OK;
2858}
2859
2860// https://github.com/rozbb/waict-integrity-draft/
2861nsresult nsHttpChannel::ProcessWAICTHeader() {
2862#ifdef NIGHTLY_BUILD1
2863 if (!StaticPrefs::security_waict_downgrade_protection_enable()) {
2864 return NS_OK;
2865 }
2866
2867 // The WAICT header is only relevant for document loads.
2868 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
2869 if (type != ExtContentPolicy::TYPE_DOCUMENT &&
2870 type != ExtContentPolicy::TYPE_SUBDOCUMENT) {
2871 return NS_OK;
2872 }
2873
2874 nsISiteIntegrityService* integrityService =
2875 gHttpHandler->GetSiteIntegrityService();
2876 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"
, 2876); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2877
2878 // Unlike HSTS, WAICT is supported for HTTP as well, so we need to use the
2879 // correct helper.
2880 OriginAttributes originAttributes;
2881 if (mURI->SchemeIs("https")) {
2882 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2883
)
2883 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2883
)
) {
2884 return NS_ERROR_FAILURE;
2885 }
2886 } else {
2887 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2888
)
2888 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2888
)
) {
2889 return NS_ERROR_FAILURE;
2890 }
2891 }
2892
2893 nsAutoCString headerValue;
2894 nsresult rv =
2895 mResponseHead->GetHeader(nsHttp::Integrity_Policy_WAICT, headerValue);
2896 if (rv == NS_ERROR_NOT_AVAILABLE || headerValue.IsEmpty()) {
2897 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)
2898 ("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)
2899 "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)
;
2900
2901 bool isProtected = false;
2902 rv = integrityService->IsProtectedURI(mURI, originAttributes, &isProtected);
2903 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2904 return rv;
2905 }
2906
2907 if (isProtected) {
2908 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)
2909 ("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)
2910 "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)
;
2911 Cancel(NS_ERROR_CORRUPTED_CONTENT);
2912 DoNotifyListener();
2913 return NS_ERROR_CORRUPTED_CONTENT;
2914 }
2915
2916 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)
;
2917 return NS_OK;
2918 }
2919 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"
, 2919)
) {
2920 return rv;
2921 }
2922#endif
2923
2924 return NS_OK;
2925}
2926
2927/**
2928 * Decide whether or not to remember Strict-Transport-Security, and whether
2929 * or not to enforce channel integrity.
2930 *
2931 * @return NS_ERROR_FAILURE if there's security information missing even though
2932 * it's an HTTPS connection.
2933 */
2934nsresult nsHttpChannel::ProcessSecurityHeaders() {
2935 // If this channel is not loading securely, STS or PKP doesn't do anything.
2936 // In the case of HSTS, the upgrade to HTTPS takes place earlier in the
2937 // channel load process.
2938 if (!mURI->SchemeIs("https")) {
2939 return NS_OK;
2940 }
2941
2942 if (IsBrowsingContextDiscarded()) {
2943 return NS_OK;
2944 }
2945
2946 nsAutoCString asciiHost;
2947 nsresult rv = mURI->GetAsciiHost(asciiHost);
2948 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"
, 2948); return NS_OK; } } while (false)
;
2949
2950 // If the channel is not a hostname, but rather an IP, do not process STS
2951 // or PKP headers
2952 if (HostIsIPLiteral(asciiHost)) {
2953 return NS_OK;
2954 }
2955
2956 // mSecurityInfo may not always be present, and if it's not then it is okay
2957 // to just disregard any security headers since we know nothing about the
2958 // security of the connection.
2959 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"
, 2959); return NS_OK; } } while (false)
;
2960
2961 // Only process HSTS headers for first-party loads. This prevents a
2962 // proliferation of useless HSTS state for partitioned third parties.
2963 if (!mLoadInfo->GetIsThirdPartyContextToTopWindow()) {
2964 rv = ProcessHSTSHeader(mSecurityInfo);
2965 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"
, 2965); return rv; } } while (false)
;
2966 }
2967
2968 return NS_OK;
2969}
2970
2971bool nsHttpChannel::IsHTTPS() { return mURI->SchemeIs("https"); }
2972
2973void nsHttpChannel::ProcessSSLInformation() {
2974 // If this is HTTPS, record any use of RSA so that Key Exchange Algorithm
2975 // can be whitelisted for TLS False Start in future sessions. We could
2976 // do the same for DH but its rarity doesn't justify the lookup.
2977
2978 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) || !mSecurityInfo || !IsHTTPS() ||
2979 mPrivateBrowsing) {
2980 return;
2981 }
2982
2983 if (!mSecurityInfo) {
2984 return;
2985 }
2986
2987 uint32_t state;
2988 if (NS_SUCCEEDED(mSecurityInfo->GetSecurityState(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mSecurityInfo->
GetSecurityState(&state))), 1)))
&&
2989 (state & nsIWebProgressListener::STATE_IS_BROKEN)) {
2990 // Send weak crypto warnings to the web console
2991 if (state & nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
2992 nsString consoleErrorTag = u"WeakCipherSuiteWarning"_ns;
2993 nsString consoleErrorCategory = u"SSL"_ns;
2994 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2995 }
2996 }
2997
2998 uint16_t tlsVersion;
2999 nsresult rv = mSecurityInfo->GetProtocolVersion(&tlsVersion);
3000 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
3001 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_2 &&
3002 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_3) {
3003 nsString consoleErrorTag = u"DeprecatedTLSVersion2"_ns;
3004 nsString consoleErrorCategory = u"TLS"_ns;
3005 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
3006 }
3007}
3008
3009void nsHttpChannel::ProcessAltService(nsHttpConnectionInfo* aTransConnInfo) {
3010 // e.g. Alt-Svc: h2=":443"; ma=60
3011 // e.g. Alt-Svc: h2="otherhost:443"
3012 // Alt-Svc = 1#( alternative *( OWS ";" OWS parameter ) )
3013 // alternative = protocol-id "=" alt-authority
3014 // protocol-id = token ; percent-encoded ALPN protocol identifier
3015 // alt-authority = quoted-string ; containing [ uri-host ] ":" port
3016
3017 if (!LoadAllowAltSvc()) { // per channel opt out
3018 return;
3019 }
3020
3021 if (mWebTransportSessionEventListener) {
3022 return;
3023 }
3024
3025 if (!gHttpHandler->AllowAltSvc() || (mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7))) {
3026 return;
3027 }
3028
3029 if (IsBrowsingContextDiscarded()) {
3030 return;
3031 }
3032
3033 nsAutoCString scheme;
3034 mURI->GetScheme(scheme);
3035 bool isHttp = scheme.EqualsLiteral("http");
3036 if (!isHttp && !scheme.EqualsLiteral("https")) {
3037 return;
3038 }
3039
3040 nsAutoCString altSvc;
3041 (void)mResponseHead->GetHeader(nsHttp::Alternate_Service, altSvc);
3042 if (altSvc.IsEmpty()) {
3043 return;
3044 }
3045
3046 if (!nsHttp::IsReasonableHeaderValue(altSvc)) {
3047 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)
;
3048 return;
3049 }
3050
3051 nsAutoCString originHost;
3052 int32_t originPort = 80;
3053 mURI->GetPort(&originPort);
3054 if (NS_FAILED(mURI->GetAsciiHost(originHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(mURI->GetAsciiHost
(originHost))), 0)))
) {
3055 return;
3056 }
3057
3058 nsCOMPtr<nsIInterfaceRequestor> callbacks;
3059 nsCOMPtr<nsProxyInfo> proxyInfo;
3060 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
3061 getter_AddRefs(callbacks));
3062
3063 if (mProxyInfo) {
3064 proxyInfo = do_QueryInterface(mProxyInfo);
3065 }
3066
3067 OriginAttributes originAttributes;
3068 // Regular principal in case we have a proxy.
3069 if (proxyInfo &&
3070 !StaticPrefs::privacy_partition_network_state_connection_with_proxy()) {
3071 StoragePrincipalHelper::GetOriginAttributes(
3072 this, originAttributes, StoragePrincipalHelper::eRegularPrincipal);
3073 } else {
3074 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
3075 this, originAttributes);
3076 }
3077
3078 AltSvcMapping::ProcessHeader(altSvc, scheme, originHost, originPort,
3079 mUsername, mPrivateBrowsing, callbacks,
3080 proxyInfo, mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7),
3081 originAttributes, aTransConnInfo);
3082}
3083
3084nsresult nsHttpChannel::ProcessResponse(nsHttpConnectionInfo* aConnInfo) {
3085 uint32_t httpStatus = mResponseHead->Status();
3086
3087 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)
3088 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)
;
3089
3090 // Gather data on whether the transaction and page (if this is
3091 // the initial page load) is being loaded with SSL.
3092 glean::http::transaction_is_ssl
3093 .EnumGet(static_cast<glean::http::TransactionIsSslLabel>(
3094 mConnectionInfo->EndToEndSSL()))
3095 .Add();
3096 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
3097 glean::http::pageload_is_ssl
3098 .EnumGet(static_cast<glean::http::PageloadIsSslLabel>(
3099 mConnectionInfo->EndToEndSSL()))
3100 .Add();
3101 }
3102
3103 if (Telemetry::CanRecordPrereleaseData()) {
3104 // Gather data on various response status to monitor any increased frequency
3105 // of auth failures due to Bug 1896350
3106 switch (httpStatus) {
3107 case 200:
3108 mozilla::glean::networking::http_response_status_code.Get("200_ok"_ns)
3109 .Add(1);
3110 break;
3111 case 301:
3112 mozilla::glean::networking::http_response_status_code
3113 .Get("301_moved_permanently"_ns)
3114 .Add(1);
3115 break;
3116 case 302:
3117 mozilla::glean::networking::http_response_status_code
3118 .Get("302_found"_ns)
3119 .Add(1);
3120 break;
3121 case 304:
3122 mozilla::glean::networking::http_response_status_code
3123 .Get("304_not_modified"_ns)
3124 .Add(1);
3125 break;
3126 case 307:
3127 mozilla::glean::networking::http_response_status_code
3128 .Get("307_temporary_redirect"_ns)
3129 .Add(1);
3130 break;
3131 case 308:
3132 mozilla::glean::networking::http_response_status_code
3133 .Get("308_permanent_redirect"_ns)
3134 .Add(1);
3135 break;
3136 case 400:
3137 mozilla::glean::networking::http_response_status_code
3138 .Get("400_bad_request"_ns)
3139 .Add(1);
3140 break;
3141 case 401:
3142 mozilla::glean::networking::http_response_status_code
3143 .Get("401_unauthorized"_ns)
3144 .Add(1);
3145 break;
3146 case 403:
3147 mozilla::glean::networking::http_response_status_code
3148 .Get("403_forbidden"_ns)
3149 .Add(1);
3150 break;
3151 case 404:
3152 mozilla::glean::networking::http_response_status_code
3153 .Get("404_not_found"_ns)
3154 .Add(1);
3155 break;
3156 case 421:
3157 mozilla::glean::networking::http_response_status_code
3158 .Get("421_misdirected_request"_ns)
3159 .Add(1);
3160 break;
3161 case 425:
3162 mozilla::glean::networking::http_response_status_code
3163 .Get("425_too_early"_ns)
3164 .Add(1);
3165 break;
3166 case 429:
3167 mozilla::glean::networking::http_response_status_code
3168 .Get("429_too_many_requests"_ns)
3169 .Add(1);
3170 break;
3171 case 500:
3172 mozilla::glean::networking::http_response_status_code
3173 .Get("other_5xx"_ns)
3174 .Add(1);
3175 break;
3176 default:
3177 if (httpStatus >= 400 && httpStatus < 500) {
3178 mozilla::glean::networking::http_response_status_code
3179 .Get("other_4xx"_ns)
3180 .Add(1);
3181 } else if (httpStatus > 500) {
3182 mozilla::glean::networking::http_response_status_code
3183 .Get("other_5xx"_ns)
3184 .Add(1);
3185 } else {
3186 mozilla::glean::networking::http_response_status_code.Get("other"_ns)
3187 .Add(1);
3188 }
3189 break;
3190 }
3191 }
3192
3193 // We use GetReferringPage because mReferrerInfo may not be set at all(this is
3194 // especially useful in xpcshell tests, where we don't have an actual pageload
3195 // to get a referrer from).
3196 // Only allow 407 (authentication required) to continue
3197 if (mTransaction && mTransaction->ProxyConnectFailed() && httpStatus != 407) {
3198 return ProcessFailedProxyConnect(httpStatus);
3199 }
3200
3201 ProcessSSLInformation();
3202
3203 // notify "http-on-examine-response" observers
3204 gHttpHandler->OnExamineResponse(this);
3205
3206 MaybeSuspendAfterExamineResponse();
3207
3208 return ContinueProcessResponse1(aConnInfo);
3209}
3210
3211void nsHttpChannel::AsyncContinueProcessResponse(
3212 nsHttpConnectionInfo* aConnInfo) {
3213 nsresult rv;
3214 rv = ContinueProcessResponse1(aConnInfo);
3215 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3216 // A synchronous failure here would normally be passed as the return
3217 // value from OnStartRequest, which would in turn cancel the request.
3218 // If we're continuing asynchronously, we need to cancel the request
3219 // ourselves.
3220 (void)Cancel(rv);
3221 }
3222}
3223
3224nsresult nsHttpChannel::ContinueProcessResponse1(
3225 nsHttpConnectionInfo* aConnInfo) {
3226 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"
, 3226); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 3226); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3227 nsresult rv = NS_OK;
3228
3229 if (mSuspendCount) {
3230 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)
3231 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3232 mCallOnResume = [connInfo = RefPtr{aConnInfo}](nsHttpChannel* self) {
3233 self->AsyncContinueProcessResponse(connInfo);
3234 return NS_OK;
3235 };
3236 return NS_OK;
3237 }
3238
3239 // Check if request was cancelled during http-on-examine-response.
3240 if (mCanceled) {
3241 return CallOnStartRequest();
3242 }
3243
3244 uint32_t httpStatus = mResponseHead->Status();
3245
3246 // STS, Cookies and Alt-Service should not be handled on proxy failure.
3247 // If proxy CONNECT response needs to complete, wait to process connection
3248 // for Strict-Transport-Security.
3249 if (!(mTransaction && mTransaction->ProxyConnectFailed()) &&
3250 (httpStatus != 407)) {
3251 // This block parses the cookie header, collects any cookie changes,
3252 // and sends them to the parent actor.
3253 {
3254 RefPtr<CookieObserver> cookieObserver;
3255 RefPtr<HttpChannelParent> httpParent;
3256 CookieServiceParent::CookieProcessingGuard cookieProcessingGuard;
3257
3258 // Skip parent channel interaction for background revalidating channels.
3259 if (!LoadOnStartRequestCalled() && !mStaleRevalidation) {
3260 // This can only happen when a range request is created again in
3261 // nsHttpChannel::ContinueOnStopRequest. If OnStartRequest is already
3262 // called, we shouldn't call SetCookieHeaders.
3263
3264 MaybeInitializeCookieProcessingGuard(this, cookieProcessingGuard,
3265 cookieObserver, httpParent,
3266 httpStatus);
3267 }
3268
3269 CookieVisitor cookieVisitor(mResponseHead.get());
3270 SetCookieHeaders(cookieVisitor.CookieHeaders());
3271
3272 if (cookieObserver) {
3273 nsTArray<CookieChange> cookieChanges;
3274 cookieObserver->StealChanges(cookieChanges);
3275
3276 if (!cookieChanges.IsEmpty()) {
3277 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"
, 3277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpParent"
")"); do { MOZ_CrashSequence(__null, 3277); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3278 httpParent->SetCookieChanges(std::move(cookieChanges));
3279 }
3280 }
3281 }
3282
3283 rv = ProcessWAICTHeader();
3284 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3285 return rv;
3286 }
3287
3288 // Given a successful connection, process any STS or PKP data that's
3289 // relevant.
3290 if (NS_FAILED(ProcessSecurityHeaders())((bool)(__builtin_expect(!!(NS_FAILED_impl(ProcessSecurityHeaders
())), 0)))
) {
3291 NS_WARNING("ProcessSecurityHeaders failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSecurityHeaders failed, continuing load."
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 3291)
;
3292 }
3293
3294 if ((httpStatus < 500) && (httpStatus != 421)) {
3295 ProcessAltService(aConnInfo);
3296 }
3297 }
3298
3299 if (LoadConcurrentCacheAccess() && LoadCachedContentIsPartial() &&
3300 httpStatus != 206) {
3301 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)
3302 (" 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)
3303 "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)
;
3304 return NS_ERROR_CORRUPTED_CONTENT;
3305 }
3306
3307 if (httpStatus != 401 && httpStatus != 407) {
3308 // reset the authentication's current continuation state because ourvr
3309 // last authentication attempt has been completed successfully
3310 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", 3310
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3310); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3311 rv = mAuthProvider ? mAuthProvider->Disconnect(NS_ERROR_ABORT)
3312 : NS_ERROR_UNEXPECTED;
3313 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3314 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)
;
3315 }
3316 mAuthProvider = nullptr;
3317 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)
;
3318 }
3319
3320 gHttpHandler->OnAfterExamineResponse(this);
3321
3322 if (mResponseHead && mResponseHead->HasHeader(nsHttp::Clear_Site_Data)) {
3323 if (nsCOMPtr<nsIObserverService> obsService =
3324 services::GetObserverService()) {
3325 obsService->NotifyObservers(static_cast<nsIHttpChannel*>(this),
3326 "clear-site-data", nullptr);
3327 }
3328 }
3329
3330 // No process switch needed, continue as normal.
3331 return ContinueProcessResponse2(rv);
3332}
3333
3334nsresult nsHttpChannel::ContinueProcessResponse2(nsresult rv) {
3335 if (mSuspendCount) {
3336 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)
3337 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3338 mCallOnResume = [rv](nsHttpChannel* self) {
3339 (void)self->ContinueProcessResponse2(rv);
3340 return NS_OK;
3341 };
3342 return NS_OK;
3343 }
3344
3345 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCanceled) {
3346 // The process switch failed, cancel this channel.
3347 Cancel(rv);
3348 return CallOnStartRequest();
3349 }
3350
3351 if (mAPIRedirectTo && !mCanceled) {
3352 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", 3352
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 3352); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3353
3354 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
3355 rv = StartRedirectChannelToURI(
3356 mAPIRedirectTo->first(),
3357 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_TEMPORARY |
3358 nsIChannelEventSink::REDIRECT_TRANSPARENT
3359 : nsIChannelEventSink::REDIRECT_TEMPORARY);
3360 mAPIRedirectTo = Nothing();
3361 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3362 return NS_OK;
3363 }
3364 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
3365 }
3366
3367 // Hack: ContinueProcessResponse3 uses NS_OK to detect successful
3368 // redirects, so we distinguish this codepath (a non-redirect that's
3369 // processing normally) by passing in a bogus error code.
3370 return ContinueProcessResponse3(NS_BINDING_FAILED);
3371}
3372
3373nsresult nsHttpChannel::ContinueProcessResponse3(nsresult rv) {
3374 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)
3375 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)
;
3376
3377 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3378 // redirectTo() has passed through, we don't want to go on with
3379 // this channel. It will now be canceled by the redirect handling
3380 // code that called this function.
3381 return NS_OK;
3382 }
3383
3384 rv = NS_OK;
3385
3386 uint32_t httpStatus = mResponseHead->Status();
3387 bool transactionRestarted = mTransaction->TakeRestartedState();
3388
3389 // handle different server response categories. Note that we handle
3390 // caching or not caching of error pages in
3391 // nsHttpResponseHead::MustValidate; if you change this switch, update that
3392 // one
3393 switch (httpStatus) {
3394 case 200:
3395 case 203:
3396 // Per RFC 2616, 14.35.2, "A server MAY ignore the Range header".
3397 // So if a server does that and sends 200 instead of 206 that we
3398 // expect, notify our caller.
3399 // However, if we wanted to start from the beginning, let it go through
3400 if (LoadResuming() && mStartPos != 0) {
3401 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)
;
3402 Cancel(NS_ERROR_NOT_RESUMABLE);
3403 rv = CallOnStartRequest();
3404 break;
3405 }
3406 // these can normally be cached
3407 rv = ProcessNormal();
3408 MaybeInvalidateCacheEntryForSubsequentGet();
3409 break;
3410 case 206:
3411 if (LoadCachedContentIsPartial()) { // an internal byte range request...
3412 auto func = [](auto* self, nsresult aRv) {
3413 return self->ContinueProcessResponseAfterPartialContent(aRv);
3414 };
3415 rv = ProcessPartialContent(func);
3416 // Directly call ContinueProcessResponseAfterPartialContent if channel
3417 // is not suspended or ProcessPartialContent throws.
3418 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3419 return ContinueProcessResponseAfterPartialContent(rv);
3420 }
3421 return NS_OK;
3422 } else {
3423 mCacheInputStream.CloseAndRelease();
3424 rv = ProcessNormal();
3425 }
3426 break;
3427 case 301:
3428 case 302:
3429 case 303:
3430 case 307:
3431 case 308:
3432#if 0
3433 case 305: // disabled as a security measure (see bug 187996).
3434#endif
3435 // RFC 9110: 303 responses are cacheable, but only with explicit
3436 // freshness information (max-age or Expires). Without these directives,
3437 // 303 should not be cached.
3438 if (httpStatus == 303) {
3439 uint32_t freshnessLifetime = 0;
3440 bool hasFreshness =
3441 (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
ComputeFreshnessLifetime(&freshnessLifetime))), 1)))
3442 mResponseHead->ComputeFreshnessLifetime(&freshnessLifetime))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
ComputeFreshnessLifetime(&freshnessLifetime))), 1)))
&&
3443 freshnessLifetime > 0) ||
3444 mResponseHead->HasHeader(nsHttp::Expires);
3445 if (mResponseHead->NoStore() || mResponseHead->NoCache() ||
3446 !hasFreshness) {
3447 CloseCacheEntry(false);
3448 }
3449 }
3450 // don't store the response body for redirects
3451 MaybeInvalidateCacheEntryForSubsequentGet();
3452 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
3453 rv = AsyncProcessRedirection(httpStatus);
3454 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3455 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
3456 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)
3457 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)
;
3458 // don't cache failed redirect responses.
3459 if (mCacheEntry) mCacheEntry->AsyncDoom(nullptr);
3460 if (DoNotRender3xxBody(rv)) {
3461 mStatus = rv;
3462 DoNotifyListener();
3463 } else {
3464 rv = ContinueProcessResponse4(rv);
3465 }
3466 }
3467 break;
3468 case 304:
3469 if (!ShouldBypassProcessNotModified()) {
3470 auto func = [](auto* self, nsresult aRv) {
3471 return self->ContinueProcessResponseAfterNotModified(aRv);
3472 };
3473 rv = ProcessNotModified(func);
3474 // Directly call ContinueProcessResponseAfterNotModified if channel
3475 // is not suspended or ProcessNotModified throws.
3476 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3477 return ContinueProcessResponseAfterNotModified(rv);
3478 }
3479 return NS_OK;
3480 }
3481
3482 // Don't cache uninformative 304
3483 if (LoadCustomConditionalRequest()) {
3484 CloseCacheEntry(false);
3485 }
3486
3487 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3488 rv = ProcessNormal();
3489 }
3490 break;
3491 case 401:
3492 case 407:
3493 if (MOZ_UNLIKELY(httpStatus == 407 && transactionRestarted)(__builtin_expect(!!(httpStatus == 407 && transactionRestarted
), 0))
) {
3494 // The transaction has been internally restarted. We want to
3495 // authenticate to the proxy again, so reuse either cached credentials
3496 // or use default credentials for NTLM/Negotiate. This prevents
3497 // considering the previously used credentials as invalid.
3498 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", 3498
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3498); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3499 if (!mAuthProvider) {
3500 mStatus = NS_ERROR_UNEXPECTED;
3501 return ProcessNormal();
3502 }
3503 mAuthProvider->ClearProxyIdent();
3504 }
3505 if (!LoadAuthRedirectedChannel() &&
3506 MOZ_UNLIKELY(LoadCustomAuthHeader())(__builtin_expect(!!(LoadCustomAuthHeader()), 0)) && httpStatus == 401) {
3507 // When a custom auth header fails, we don't want to try
3508 // any cached credentials, nor we want to ask the user.
3509 // It's up to the consumer to re-try w/o setting a custom
3510 // auth header if cached credentials should be attempted.
3511 rv = NS_ERROR_FAILURE;
3512 } else if (httpStatus == 401 && LoadUploadStreamIsStreaming() &&
3513 !(mLoadFlags & LOAD_ANONYMOUS)) {
3514 // A body whose source is null cannot be resubmitted with credentials,
3515 // so this is a network error rather than an auth prompt. Ahead of the
3516 // frame-ancestor check, which would still deliver the 401. Still too
3517 // broad for mode "cors" with credentials "include", which the channel
3518 // cannot tell apart from the cases the spec fails here.
3519 // https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch
3520 rv = NS_ERROR_NET_BODY_NOT_REPLAYABLE;
3521 } else if (httpStatus == 401 &&
3522 !nsContentSecurityUtils::CheckCSPFrameAncestorAndXFO(this)) {
3523 // CSP Frame Ancestor and X-Frame-Options check has failed
3524 // Do not prompt http auth - Bug 1629307
3525 rv = NS_ERROR_FAILURE;
3526 } else {
3527 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", 3527
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3528 rv = mAuthProvider
3529 ? mAuthProvider->ProcessAuthentication(
3530 httpStatus, mConnectionInfo->EndToEndSSL() &&
3531 mTransaction &&
3532 mTransaction->ProxyConnectFailed())
3533 : NS_ERROR_UNEXPECTED;
3534 }
3535 if (rv == NS_ERROR_IN_PROGRESS) {
3536 // authentication prompt has been invoked and result
3537 // is expected asynchronously
3538 mIsAuthChannel = true;
3539 mAuthRetryPending = true;
3540 if (httpStatus == 407 ||
3541 (mTransaction && mTransaction->ProxyConnectFailed())) {
3542 StoreProxyAuthPending(true);
3543 }
3544
3545 // suspend the transaction pump to stop receiving the
3546 // unauthenticated content data. We will throw that data
3547 // away when user provides credentials or resume the pump
3548 // when user refuses to authenticate.
3549 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)
3550 ("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)
3551 "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)
;
3552 Suspend();
3553
3554#ifdef DEBUG1
3555 // This is for test purposes only. See bug 1683176 for details.
3556 gHttpHandler->OnTransactionSuspendedDueToAuthentication(this);
3557#endif
3558 rv = NS_OK;
3559 } else if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3560 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)
3561 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)
;
3562 if (mTransaction && mTransaction->ProxyConnectFailed()) {
3563 return ProcessFailedProxyConnect(httpStatus);
3564 }
3565 if (rv == NS_ERROR_BASIC_HTTP_AUTH_DISABLED ||
3566 rv == NS_ERROR_NET_BODY_NOT_REPLAYABLE) {
3567 mStatus = rv;
3568 }
3569 rv = ProcessNormal();
3570 } else {
3571 mIsAuthChannel = true;
3572 mAuthRetryPending = true;
3573 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
3574 if (NS_SUCCEEDED(RedirectToNewChannelForAuthRetry())((bool)(__builtin_expect(!!(!NS_FAILED_impl(RedirectToNewChannelForAuthRetry
())), 1)))
) {
3575 return NS_OK;
3576 }
3577 mAuthRetryPending = false;
3578 rv = ProcessNormal();
3579 }
3580 }
3581 break;
3582
3583 case 408:
3584 case 425:
3585 case 429:
3586 // Do not cache 408, 425 and 429.
3587 CloseCacheEntry(false);
3588 [[fallthrough]]; // process normally
3589 default:
3590 rv = ProcessNormal();
3591 MaybeInvalidateCacheEntryForSubsequentGet();
3592 break;
3593 }
3594
3595 UpdateCacheDisposition(false, false);
3596 return rv;
3597}
3598
3599nsresult nsHttpChannel::ContinueProcessResponseAfterPartialContent(
3600 nsresult aRv) {
3601 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)
3602 ("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)
3603 "[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)
3604 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)
;
3605
3606 UpdateCacheDisposition(false, NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1))));
3607 return aRv;
3608}
3609
3610nsresult nsHttpChannel::ContinueProcessResponseAfterNotModified(nsresult aRv) {
3611 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)
3612 ("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)
3613 "[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)
3614 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)
;
3615
3616 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))) {
3617 StoreTransactionReplaced(true);
3618 UpdateCacheDisposition(true, false);
3619 return NS_OK;
3620 }
3621
3622 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)
3623 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)
;
3624
3625 // We cannot read from the cache entry, it might be in an
3626 // inconsistent state. Doom it and redirect the channel
3627 // to the same URI to reload from the network.
3628 mCacheInputStream.CloseAndRelease();
3629 if (mCacheEntry) {
3630 mCacheEntry->AsyncDoom(nullptr);
3631 mCacheEntry = nullptr;
3632 }
3633
3634 nsresult rv =
3635 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
3636 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3637 return NS_OK;
3638 }
3639
3640 // Don't cache uninformative 304
3641 if (LoadCustomConditionalRequest()) {
3642 CloseCacheEntry(false);
3643 }
3644
3645 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3646 rv = ProcessNormal();
3647 }
3648
3649 UpdateCacheDisposition(false, false);
3650 return rv;
3651}
3652
3653static void ReportHttpResponseVersion(HttpVersion version) {
3654 if (Telemetry::CanRecordPrereleaseData()) {
3655 glean::http::response_version.AccumulateSingleSample(
3656 static_cast<uint32_t>(version));
3657 }
3658 mozilla::glean::networking::http_response_version
3659 .Get(HttpVersionToTelemetryLabel(version))
3660 .Add(1);
3661}
3662
3663void nsHttpChannel::UpdateCacheDisposition(bool aSuccessfulReval,
3664 bool aPartialContentUsed) {
3665 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)
3666 "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)
3667 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)
3668 !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)
3669 : (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)
;
3670 CacheDisposition cacheDisposition;
3671 if (!mDidReval) {
3672 cacheDisposition = kCacheMissed;
3673 } else if (aSuccessfulReval) {
3674 cacheDisposition = kCacheHitViaReval;
3675 } else {
3676 cacheDisposition = kCacheMissedViaReval;
3677 }
3678 mCacheDisposition = cacheDisposition;
3679
3680 if (Telemetry::CanRecordPrereleaseData()) {
3681 AccumulateCacheHitTelemetry(cacheDisposition, this);
3682 }
3683
3684 ReportHttpResponseVersion(mResponseHead->Version());
3685}
3686
3687// Only used for redirects (3XX responses)
3688nsresult nsHttpChannel::ContinueProcessResponse4(nsresult rv) {
3689 bool doNotRender = DoNotRender3xxBody(rv);
3690
3691 if (rv == NS_ERROR_DOM_BAD_URI && mRedirectURI &&
3692 !net::SchemeIsHttpOrHttps(mRedirectURI)) {
3693 // This was a blocked attempt to redirect and subvert the system by
3694 // redirecting to another protocol (perhaps javascript:)
3695 // In that case we want to throw an error instead of displaying the
3696 // non-redirected response body.
3697 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)
;
3698 doNotRender = true;
3699 rv = NS_ERROR_CORRUPTED_CONTENT;
3700 }
3701
3702 if (doNotRender) {
3703 Cancel(rv);
3704 DoNotifyListener();
3705 return rv;
3706 }
3707
3708 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3709 UpdateInhibitPersistentCachingFlag();
3710 (void)MaybeReplaceNoVarySearchAliasEntry();
3711
3712 if (mCacheEntry) {
3713 rv = UpdateExpirationTime();
3714 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3715 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)
3716 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)
;
3717 }
3718 }
3719 rv = InitCacheEntry();
3720 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3721 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)
3722 ("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)
3723 "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)
3724 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)
;
3725 }
3726 CloseCacheEntry(false);
3727 return NS_OK;
3728 }
3729
3730 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)
3731 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)
;
3732 if (mTransaction && mTransaction->ProxyConnectFailed()) {
3733 return ProcessFailedProxyConnect(mRedirectType);
3734 }
3735 return ProcessNormal();
3736}
3737
3738nsresult nsHttpChannel::ProcessNormal() {
3739 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)
;
3740
3741 return ContinueProcessNormal(NS_OK);
3742}
3743
3744nsresult nsHttpChannel::ContinueProcessNormal(nsresult rv) {
3745 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)
;
3746
3747 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3748 // Fill the failure status here, we have failed to fall back, thus we
3749 // have to report our status as failed.
3750 mStatus = rv;
3751 DoNotifyListener();
3752 return rv;
3753 }
3754
3755 rv = ProcessCrossOriginSecurityHeaders();
3756 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3757 mStatus = rv;
3758 HandleAsyncAbort();
3759 return rv;
3760 }
3761
3762 // if we're here, then any byte-range requests failed to result in a partial
3763 // response. we must clear this flag to prevent BufferPartialContent from
3764 // being called inside our OnDataAvailable (see bug 136678).
3765 StoreCachedContentIsPartial(false);
3766
3767 UpdateInhibitPersistentCachingFlag();
3768
3769 // We may need to install the cache listener before CallonStartRequest,
3770 // since InstallCacheListener can modify the Content-Encoding to remove
3771 // dcb/dcz (and perhaps others), and CallOnStartRequest() copies
3772 // Content-Encoding to send to the content process. If this doesn't
3773 // install a listener (because this isn't a dictionary or
3774 // dictionary-compressed), call it after CallOnStartRequest so that we
3775 // save the compressed data in the cache, and run the decompressor in the
3776 // content process.
3777 mIsDictionaryCompressed = false;
3778 nsAutoCString contentEncoding;
3779 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
3780 if (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
3781 contentEncoding.LowerCaseEqualsLiteral("dcz")) {
3782 mIsDictionaryCompressed = true;
3783 } else if (contentEncoding.LowerCaseFindASCII("dcb") != -1 ||
3784 contentEncoding.LowerCaseFindASCII("dcz") != -1) {
3785 // Reject responses that combine dcb/dcz with other encodings
3786 // (e.g. "dcb, gzip" or "gzip, dcz"). We don't support chained
3787 // dictionary compression with other compression methods.
3788 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)
3789 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)
;
3790 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
3791 return NS_ERROR_INVALID_CONTENT_ENCODING;
3792 }
3793
3794 (void)MaybeReplaceNoVarySearchAliasEntry();
3795
3796 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3797 // Must update expiration time early - ParseDictionary reads it, and
3798 // it's no longer done in InitCacheEntry to avoid double calculation
3799 rv = UpdateExpirationTime();
3800 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3801 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)
;
3802 }
3803
3804 // XXX We may want to consider recompressing any dcb/dcz files to save space
3805 // and improve hitrate. Downside is CPU use, complexity and perhaps delay,
3806 // maybe.
3807 nsAutoCString dictionary;
3808 if (StaticPrefs::network_http_dictionaries_enable() && IsHTTPS()) {
3809 (void)mResponseHead->GetHeader(nsHttp::Use_As_Dictionary, dictionary);
3810 if (!dictionary.IsEmpty()) {
3811 if (!ParseDictionary(mCacheEntry, mResponseHead.get(), true)) {
3812 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)
;
3813 } else {
3814 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"
, 3814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDictSaving"
")"); do { MOZ_CrashSequence(__null, 3814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3815
3816 // We need to record the hash as we save it
3817 mCacheEntry->SetDictionary(mDictSaving);
3818 }
3819 }
3820 }
3821
3822 // we would call DoInstallCacheListener() here, but it will close the
3823 // cache input stream, which causes problems if we going to be
3824 // suspended because we're replacing a active dictionary. Instead we'll
3825 // call it in ContinueProcessNormal2()
3826 } else {
3827 if (mIsDictionaryCompressed) {
3828 // We still need to decompress in the parent if it's dcb or dcz even if
3829 // not saving to the cache
3830 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)
3831 ("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)
;
3832 nsCOMPtr<nsIStreamListener> listener;
3833 // otherwise we won't convert in the parent process
3834 // XXX may be redundant, but safe
3835 SetApplyConversion(true);
3836 rv = DoApplyContentConversionsInternal(
3837 mListener, getter_AddRefs(listener), true, nullptr);
3838 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3839 return rv;
3840 }
3841 if (listener) {
3842 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)
3843 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)
;
3844 mListener = listener;
3845 mCompressListener = std::move(listener);
3846 StoreHasAppliedConversion(true);
3847 } else {
3848 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)
;
3849 // This should never happen for dictionary-compressed content (dcb/dcz)
3850 // as it MUST be decompressed in the parent process
3851 if (mIsDictionaryCompressed) {
3852 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)
3853 ("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)
3854 "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)
;
3855 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
3856 return NS_ERROR_INVALID_CONTENT_ENCODING;
3857 }
3858 }
3859 }
3860 } // else we'll call InstallCacheListener after CallOnStartRequest
3861
3862 // ParseDictionary may have resulted in our Suspend()ing this request
3863 // until the old dictionary we're replacing has been read from the cache.
3864 // If we continue we'll call InitCacheEntry() and Doom/truncate the entry
3865 // the old one is reading from.
3866 return ContinueProcessNormal2(rv);
3867}
3868
3869nsresult nsHttpChannel::ContinueProcessNormal2(nsresult rv) {
3870 if (mSuspendCount) {
3871 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)
3872 ("*** 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)
3873 "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)
3874 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)
;
3875 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)
3876 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3877 mCallOnResume = [rv](nsHttpChannel* self) {
3878 (void)self->ContinueProcessNormal2(rv);
3879 return NS_OK;
3880 };
3881 return NS_OK;
3882 }
3883
3884 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCanceled) {
3885 // The process switch failed, cancel this channel.
3886 Cancel(rv);
3887 return CallOnStartRequest();
3888 }
3889
3890 // this must be called before firing OnStartRequest, since http clients,
3891 // such as imagelib, expect our cache entry to already have the correct
3892 // expiration time (bug 87710).
3893 if (mCacheEntry) {
3894 rv = InitCacheEntry();
3895 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CloseCacheEntry(true);
3896 }
3897
3898 // CRITICAL: Check if dictionary is ready BEFORE creating decompressor.
3899 // If we create the decompressor before the dictionary is ready, it will
3900 // be created without the dictionary attached, causing decompression to fail.
3901 // The dictionary prefetch callback (in PrepareToConnect) will call Resume()
3902 // when ready, which will re-invoke ContinueProcessNormal2 via mCallOnResume.
3903 if (mIsDictionaryCompressed && mDictDecompress && mUsingDictionary &&
3904 mShouldSuspendForDictionary && !mDictDecompress->DictionaryReady()) {
3905 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)
3906 ("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)
3907 "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)
3908 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)
;
3909 Suspend();
3910 mSuspendedForDictionary = true;
3911 // Set up callback to resume processing when dictionary loads
3912 mCallOnResume = [](nsHttpChannel* self) {
3913 return self->ContinueProcessNormal3();
3914 };
3915 return NS_OK;
3916 }
3917
3918 return ContinueProcessNormal3();
3919}
3920
3921nsresult nsHttpChannel::ContinueProcessNormal3() {
3922 if (mCanceled) {
3923 return CallOnStartRequest();
3924 }
3925 nsresult rv = NS_OK;
3926
3927 // Finish post-ParseDictionary work, must be done after waiting if Suspended
3928 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3929 if (mIsDictionaryCompressed || mDictSaving) {
3930 if (MOZ_LOG_TEST(mozilla::net::gDictionaryLog,(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
3931 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
) {
3932 nsAutoCString ceDebug;
3933 if (mResponseHead) {
3934 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, ceDebug);
3935 }
3936 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)
3937 ("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)
3938 "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)
3939 "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)
3940 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)
3941 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)
;
3942 }
3943 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)
;
3944 rv = DoInstallCacheListener(mIsDictionaryCompressed || mDictSaving, 0);
3945 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3946 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)
3947 ("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)
;
3948 // Cache entry is now corrupted - we set up headers with dcb/dcz
3949 // Content-Encoding but failed to install the decompressor that would
3950 // clear it. Doom the entry to prevent serving corrupted data.
3951 CloseCacheEntry(true);
3952 }
3953 }
3954 }
3955
3956 // Check that the server sent us what we were asking for
3957 if (LoadResuming()) {
3958 // Create an entity id from the response
3959 nsAutoCString id;
3960 rv = GetEntityID(id);
3961 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3962 // If creating an entity id is not possible -> error
3963 Cancel(NS_ERROR_NOT_RESUMABLE);
3964 } else if (mResponseHead->Status() != 206 &&
3965 mResponseHead->Status() != 200) {
3966 // Probably 404 Not Found, 412 Precondition Failed or
3967 // 416 Invalid Range -> error
3968 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)
3969 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3970 Cancel(NS_ERROR_ENTITY_CHANGED);
3971 }
3972 // If we were passed an entity id, verify it's equal to the server's
3973 else if (!mEntityID.IsEmpty()) {
3974 if (!mEntityID.Equals(id)) {
3975 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)
3976 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)
;
3977 Cancel(NS_ERROR_ENTITY_CHANGED);
3978 }
3979 }
3980 }
3981
3982 rv = CallOnStartRequest();
3983 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3984
3985 // If we didn't install cache listeners to decompress above
3986 // install the cache listener now (so they'll get compressed data)
3987 if (!mIsDictionaryCompressed && !mDictSaving) {
3988 // install cache listener if we still have a cache entry open
3989 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3990 if (MOZ_LOG_TEST(mozilla::net::gDictionaryLog,(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
3991 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
&&
3992 mResponseHead) {
3993 nsAutoCString ceCheck;
3994 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, ceCheck);
3995 if (!ceCheck.IsEmpty()) {
3996 nsAutoCString uadCheck;
3997 (void)mResponseHead->GetHeader(nsHttp::Use_As_Dictionary, uadCheck);
3998 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)
3999 ("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)
4000 "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)
4001 "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)
4002 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)
4003 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)
;
4004 }
4005 }
4006 rv = InstallCacheListener();
4007 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4008 }
4009 }
4010 return NS_OK;
4011}
4012
4013nsresult nsHttpChannel::PromptTempRedirect() {
4014 if (!gHttpHandler->PromptTempRedirect()) {
4015 return NS_OK;
4016 }
4017 nsresult rv;
4018 nsCOMPtr<nsIStringBundleService> bundleService;
4019 bundleService = mozilla::components::StringBundle::Service(&rv);
4020 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4021
4022 nsCOMPtr<nsIStringBundle> stringBundle;
4023 rv =
4024 bundleService->CreateBundle(NECKO_MSGS_URL"chrome://necko/locale/necko.properties", getter_AddRefs(stringBundle));
4025 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4026
4027 nsAutoString messageString;
4028 rv = stringBundle->GetStringFromName("RepostFormData", messageString);
4029 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4030 bool repost = false;
4031
4032 nsCOMPtr<nsIPrompt> prompt;
4033 GetCallback(prompt);
4034 if (!prompt) return NS_ERROR_NO_INTERFACE;
4035
4036 prompt->Confirm(nullptr, messageString.get(), &repost);
4037 if (!repost) return NS_ERROR_FAILURE;
4038 }
4039
4040 return rv;
4041}
4042
4043nsresult nsHttpChannel::ProxyFailover() {
4044 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)
;
4045
4046 nsresult rv;
4047
4048 nsCOMPtr<nsIProtocolProxyService> pps;
4049 pps = mozilla::components::ProtocolProxy::Service(&rv);
4050 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4051
4052 nsCOMPtr<nsIProxyInfo> pi;
4053 rv = pps->GetFailoverForProxy(mConnectionInfo->ProxyInfo(), mURI, mStatus,
4054 getter_AddRefs(pi));
4055#ifdef MOZ_PROXY_DIRECT_FAILOVER1
4056 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4057 if (!StaticPrefs::network_proxy_failover_direct()) {
4058 return rv;
4059 }
4060 // If this request used a failed proxy and there is no failover available,
4061 // fallback to DIRECT connections for conservative requests.
4062 if (LoadBeConservative()) {
4063 rv = pps->NewProxyInfo("direct"_ns, ""_ns, 0, ""_ns, ""_ns, 0, UINT32_MAX(4294967295U),
4064 nullptr, getter_AddRefs(pi));
4065 }
4066#endif
4067 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4068 return rv;
4069 }
4070#ifdef MOZ_PROXY_DIRECT_FAILOVER1
4071 }
4072#endif
4073
4074 // XXXbz so where does this codepath remove us from the loadgroup,
4075 // exactly?
4076 return AsyncDoReplaceWithProxy(pi);
4077}
4078
4079void nsHttpChannel::SetHTTPSSVCRecord(
4080 already_AddRefed<nsIDNSHTTPSSVCRecord> aRecord) {
4081 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)
;
4082 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
4083 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", 4083
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mHTTPSSVCRecord"
")"); do { MOZ_CrashSequence(__null, 4083); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4084 mHTTPSSVCRecord.emplace(std::move(record));
4085}
4086
4087void nsHttpChannel::HandleAsyncRedirectChannelToHttps() {
4088 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"
, 4088); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4088); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4089
4090 if (mSuspendCount) {
4091 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)
4092 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
4093 mCallOnResume = [](nsHttpChannel* self) {
4094 self->HandleAsyncRedirectChannelToHttps();
4095 return NS_OK;
4096 };
4097 return;
4098 }
4099
4100 nsresult rv = StartRedirectChannelToHttps();
4101 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4102 rv = ContinueAsyncRedirectChannelToURI(rv);
4103 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4104 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)
4105 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)
;
4106 }
4107 }
4108}
4109
4110nsresult nsHttpChannel::StartRedirectChannelToHttps() {
4111 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)
;
4112
4113 nsCOMPtr<nsIURI> upgradedURI;
4114 nsresult rv = NS_GetSecureUpgradedURI(mURI, getter_AddRefs(upgradedURI));
4115 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"
, 4115); return rv; } } while (false)
;
4116
4117 return StartRedirectChannelToURI(
4118 upgradedURI, nsIChannelEventSink::REDIRECT_PERMANENT |
4119 nsIChannelEventSink::REDIRECT_STS_UPGRADE);
4120}
4121
4122void nsHttpChannel::HandleAsyncAPIRedirect() {
4123 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"
, 4123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4123); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4124 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"
, 4124); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4124); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4125 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"
, 4125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo->first()"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4125); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4126
4127 if (mSuspendCount) {
4128 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)
;
4129 mCallOnResume = [](nsHttpChannel* self) {
4130 self->HandleAsyncAPIRedirect();
4131 return NS_OK;
4132 };
4133 return;
4134 }
4135
4136 nsresult rv = StartRedirectChannelToURI(
4137 mAPIRedirectTo->first(),
4138 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_PERMANENT |
4139 nsIChannelEventSink::REDIRECT_TRANSPARENT
4140 : nsIChannelEventSink::REDIRECT_PERMANENT);
4141 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4142 rv = ContinueAsyncRedirectChannelToURI(rv);
4143 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4144 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)
4145 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)
;
4146 }
4147 }
4148}
4149
4150void nsHttpChannel::HandleAsyncRedirectToUnstrippedURI() {
4151 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"
, 4151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4151); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4152
4153 if (mSuspendCount) {
4154 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)
4155 ("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)
4156 "[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)
4157 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
4158 mCallOnResume = [](nsHttpChannel* self) {
4159 self->HandleAsyncRedirectToUnstrippedURI();
4160 return NS_OK;
4161 };
4162 return;
4163 }
4164
4165 nsCOMPtr<nsIURI> unstrippedURI;
4166 mLoadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
4167
4168 // Clear the unstripped URI from the loadInfo before starting redirect in case
4169 // endless redirect.
4170 mLoadInfo->SetUnstrippedURI(nullptr);
4171
4172 nsresult rv = StartRedirectChannelToURI(
4173 unstrippedURI, nsIChannelEventSink::REDIRECT_PERMANENT);
4174
4175 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4176 rv = ContinueAsyncRedirectChannelToURI(rv);
4177 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4178 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)
4179 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)
;
4180 }
4181 }
4182}
4183nsresult nsHttpChannel::RedirectToNewChannelForAuthRetry() {
4184 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)
;
4185 nsresult rv = NS_OK;
4186
4187 nsCOMPtr<nsILoadInfo> redirectLoadInfo = CloneLoadInfoForRedirect(
4188 mURI, nsIChannelEventSink::REDIRECT_INTERNAL |
4189 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4190
4191 nsCOMPtr<nsIIOService> ioService;
4192
4193 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
4194 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"
, 4194); return rv; } } while (false)
;
4195
4196 nsCOMPtr<nsIChannel> newChannel;
4197 rv = gHttpHandler->NewProxiedChannel(mURI, mProxyInfo, mProxyResolveFlags,
4198 mProxyURI, mLoadInfo,
4199 getter_AddRefs(newChannel));
4200
4201 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4201); return rv; } } while (false)
;
4202
4203 rv = SetupReplacementChannel(mURI, newChannel, true,
4204 nsIChannelEventSink::REDIRECT_INTERNAL |
4205 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4206 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"
, 4206); return rv; } } while (false)
;
4207
4208 // rewind the upload stream
4209 if (mUploadStream) {
4210 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
4211 nsresult rv = NS_ERROR_NO_INTERFACE;
4212 if (seekable) {
4213 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
4214 }
4215
4216 // This should not normally happen, but it's possible that big memory
4217 // blobs originating in the other process can't be rewinded.
4218 // In that case we just fail the request, otherwise the content length
4219 // will not match and this load will never complete.
4220 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"
, 4220); return rv; } } while (false)
;
4221 }
4222
4223 RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel);
4224
4225 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", 4225
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthProvider" ")"
); do { MOZ_CrashSequence(__null, 4225); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4226 httpChannelImpl->mAuthProvider = std::move(mAuthProvider);
4227
4228 httpChannelImpl->mProxyInfo = mProxyInfo;
4229
4230 if ((mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) ||
4231 mTransaction->HasStickyConnection()) {
4232 mConnectionInfo = mTransaction->GetConnInfo();
4233
4234 httpChannelImpl->mTransactionSticky = mTransaction;
4235
4236 if (mTransaction->Http2Disabled()) {
4237 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
4238 }
4239 if (mTransaction->Http3Disabled()) {
4240 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
4241 }
4242 }
4243 // always set sticky connection flag
4244 httpChannelImpl->mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
4245
4246 if (LoadAuthConnectionRestartable()) {
4247 httpChannelImpl->mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
4248 } else {
4249 httpChannelImpl->mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
4250 }
4251
4252 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", 4252
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo" ")"
); do { MOZ_CrashSequence(__null, 4252); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4253 httpChannelImpl->mConnectionInfo = mConnectionInfo;
4254
4255 // we need to store the state to skip unnecessary checks in the new channel
4256 httpChannelImpl->StoreAuthRedirectedChannel(true);
4257
4258 // We must copy proxy and auth header to the new channel.
4259 // Although the new channel can populate auth headers from auth cache, we
4260 // would still like to use the auth headers generated in this channel. The
4261 // main reason for doing this is that certain connection-based/stateful auth
4262 // schemes like NTLM will fail when we try generate the credentials more than
4263 // the number of times the server has presented us the challenge due to the
4264 // usage of nonce in generating the credentials Copying the auth header will
4265 // bypass generation of the credentials
4266 nsAutoCString authVal;
4267 if (NS_SUCCEEDED(GetRequestHeader("Proxy-Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Proxy-Authorization"_ns, authVal))), 1)))
) {
4268 httpChannelImpl->SetRequestHeader("Proxy-Authorization"_ns, authVal, false);
4269 }
4270 if (NS_SUCCEEDED(GetRequestHeader("Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Authorization"_ns, authVal))), 1)))
) {
4271 httpChannelImpl->SetRequestHeader("Authorization"_ns, authVal, false);
4272 }
4273
4274 httpChannelImpl->SetBlockAuthPrompt(LoadBlockAuthPrompt());
4275 mRedirectChannel = newChannel;
4276
4277 rv = gHttpHandler->AsyncOnChannelRedirect(
4278 this, newChannel,
4279 nsIChannelEventSink::REDIRECT_INTERNAL |
4280 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4281
4282 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4283
4284 // redirected channel will be opened after we receive the OnStopRequest
4285
4286 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4287 AutoRedirectVetoNotifier notifier(this, rv);
4288 mRedirectChannel = nullptr;
4289 }
4290
4291 return rv;
4292}
4293
4294nsresult nsHttpChannel::StartRedirectChannelToURI(nsIURI* upgradedURI,
4295 uint32_t flags) {
4296 return StartRedirectChannelToURI(upgradedURI, flags, [](nsIChannel*) {});
4297}
4298
4299nsresult nsHttpChannel::StartRedirectChannelToURI(
4300 nsIURI* upgradedURI, uint32_t flags,
4301 std::function<void(nsIChannel*)>&& aCallback) {
4302 nsresult rv = NS_OK;
4303 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)
;
4304
4305 nsCOMPtr<nsIChannel> newChannel;
4306 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
4307 CloneLoadInfoForRedirect(upgradedURI, flags);
4308
4309 nsCOMPtr<nsIIOService> ioService;
4310 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
4311 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"
, 4311); return rv; } } while (false)
;
4312
4313 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), upgradedURI,
4314 redirectLoadInfo,
4315 nullptr, // PerformanceStorage
4316 nullptr, // aLoadGroup
4317 nullptr, // aCallbacks
4318 nsIRequest::LOAD_NORMAL, ioService);
4319 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"
, 4319); return rv; } } while (false)
;
4320
4321 rv = SetupReplacementChannel(upgradedURI, newChannel, true, flags);
4322 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"
, 4322); return rv; } } while (false)
;
4323
4324 if (mHTTPSSVCRecord) {
4325 RefPtr<nsHttpChannel> httpChan = do_QueryObject(newChannel);
4326 nsCOMPtr<nsIDNSHTTPSSVCRecord> rec = mHTTPSSVCRecord.ref();
4327 if (httpChan && rec) {
4328 httpChan->SetHTTPSSVCRecord(rec.forget());
4329 }
4330 }
4331
4332 // Inform consumers about this fake redirect
4333 mRedirectChannel = newChannel;
4334
4335 aCallback(newChannel);
4336
4337 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
4338 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
4339
4340 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4341
4342 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4343 AutoRedirectVetoNotifier notifier(this, rv);
4344
4345 /* Remove the async call to ContinueAsyncRedirectChannelToURI().
4346 * It is called directly by our callers upon return (to clean up
4347 * the failed redirect). */
4348 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
4349 }
4350
4351 return rv;
4352}
4353
4354nsresult nsHttpChannel::ContinueAsyncRedirectChannelToURI(nsresult rv) {
4355 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)
;
4356
4357 // Since we handle mAPIRedirectTo uri also after on-examine-response handler
4358 // rather drop it here to avoid any redirect loops, even just hypothetical.
4359 mAPIRedirectTo = Nothing();
4360
4361 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4362 rv = OpenRedirectChannel(rv);
4363 }
4364
4365 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4366 // Cancel the channel here, the update to https had been vetoed
4367 // but from the security reasons we have to discard the whole channel
4368 // load.
4369 Cancel(rv);
4370 }
4371
4372 if (mLoadGroup) {
4373 mLoadGroup->RemoveRequest(this, nullptr, mStatus);
4374 }
4375
4376 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCachePump && !mTransactionPump) {
4377 // We have to manually notify the listener because there is not any pump
4378 // that would call our OnStart/StopRequest after resume from waiting for
4379 // the redirect callback.
4380 DoNotifyListener();
4381 }
4382
4383 return rv;
4384}
4385
4386nsresult nsHttpChannel::OpenRedirectChannel(nsresult rv) {
4387 AutoRedirectVetoNotifier notifier(this, rv);
4388
4389 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4390
4391 if (!mRedirectChannel) {
4392 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)
4393 "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)
;
4394 return NS_ERROR_FAILURE;
4395 }
4396
4397 // Make sure to do this after we received redirect veto answer,
4398 // i.e. after all sinks had been notified
4399 mRedirectChannel->SetOriginalURI(mOriginalURI);
4400
4401 // open new channel
4402 rv = mRedirectChannel->AsyncOpen(mListener);
4403
4404 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"
, 4404); return rv; } } while (false)
;
4405
4406 mStatus = NS_BINDING_REDIRECTED;
4407
4408 notifier.RedirectSucceeded();
4409
4410 // Report timing data if e10s is disabled
4411 MaybeReportTimingDataForRedirect(mRedirectChannel);
4412
4413 ReleaseListeners();
4414
4415 return NS_OK;
4416}
4417
4418nsresult nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi) {
4419 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)
;
4420 nsresult rv;
4421
4422 nsCOMPtr<nsIChannel> newChannel;
4423 rv = gHttpHandler->NewProxiedChannel(mURI, pi, mProxyResolveFlags, mProxyURI,
4424 mLoadInfo, getter_AddRefs(newChannel));
4425 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4426
4427 uint32_t flags = nsIChannelEventSink::REDIRECT_INTERNAL;
4428
4429 rv = SetupReplacementChannel(mURI, newChannel, true, flags);
4430 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4431
4432 // Inform consumers about this fake redirect
4433 mRedirectChannel = newChannel;
4434
4435 PushRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
4436 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
4437
4438 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4439
4440 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4441 AutoRedirectVetoNotifier notifier(this, rv);
4442 PopRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
4443 }
4444
4445 return rv;
4446}
4447
4448nsresult nsHttpChannel::ResolveProxy() {
4449 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)
;
4450
4451 nsresult rv;
4452
4453 nsCOMPtr<nsIProtocolProxyService> pps;
4454 pps = mozilla::components::ProtocolProxy::Service(&rv);
4455 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4456
4457 // using the nsIProtocolProxyService2 allows a minor performance
4458 // optimization, but if an add-on has only provided the original interface
4459 // then it is ok to use that version.
4460 nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
4461 if (pps2) {
4462 rv = pps2->AsyncResolve2(this, mProxyResolveFlags, this, nullptr,
4463 getter_AddRefs(mProxyRequest));
4464 } else {
4465 rv = pps->AsyncResolve(static_cast<nsIChannel*>(this), mProxyResolveFlags,
4466 this, nullptr, getter_AddRefs(mProxyRequest));
4467 }
4468
4469 return rv;
4470}
4471
4472bool nsHttpChannel::ResponseWouldVary(nsICacheEntry* entry) {
4473 nsresult rv;
4474 nsAutoCString buf, metaKey;
4475 (void)mCachedResponseHead->GetHeader(nsHttp::Vary, buf);
4476
4477 constexpr auto prefix = "request-"_ns;
4478
4479 // enumerate the elements of the Vary header...
4480 for (const nsACString& token :
4481 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4482 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)
4483 ("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)
4484 "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)
4485 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)
;
4486 //
4487 // if "*", then assume response would vary. technically speaking,
4488 // "Vary: header, *" is not permitted, but we allow it anyways.
4489 //
4490 // We hash values of cookie-headers for the following reasons:
4491 //
4492 // 1- cookies can be very large in size
4493 //
4494 // 2- cookies may contain sensitive information. (for parity with
4495 // out policy of not storing Set-cookie headers in the cache
4496 // meta data, we likewise do not want to store cookie headers
4497 // here.)
4498 //
4499 if (token.EqualsLiteral("*")) {
4500 return true; // if we encounter this, just get out of here
4501 }
4502
4503 // build cache meta data key...
4504 metaKey = prefix + token;
4505
4506 // check the last value of the given request header to see if it has
4507 // since changed. if so, then indeed the cached response is invalid.
4508 nsCString lastVal;
4509 entry->GetMetaDataElement(metaKey.get(), getter_Copies(lastVal));
4510 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)
4511 ("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)
4512 "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)
4513 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)
;
4514
4515 // Look for value of "Cookie" in the request headers
4516 nsHttpAtom atom = nsHttp::ResolveAtom(token);
4517 nsAutoCString newVal;
4518 bool hasHeader = NS_SUCCEEDED(mRequestHead.GetHeader(atom, newVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(atom, newVal))), 1)))
;
4519 if (!lastVal.IsEmpty()) {
4520 // value for this header in cache, but no value in request
4521 if (!hasHeader) {
4522 return true; // yes - response would vary
4523 }
4524
4525 // If this is a cookie-header, stored metadata is not
4526 // the value itself but the hash. So we also hash the
4527 // outgoing value here in order to compare the hashes
4528 nsAutoCString hash;
4529 if (atom == nsHttp::Cookie) {
4530 rv = Hash(newVal.get(), hash);
4531 // If hash failed, be conservative (the cached hash
4532 // exists at this point) and claim response would vary
4533 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return true;
4534 newVal = std::move(hash);
4535
4536 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)
4537 ("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)
4538 "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)
4539 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)
;
4540 }
4541
4542 if (!newVal.Equals(lastVal)) {
4543 return true; // yes, response would vary
4544 }
4545
4546 } else if (hasHeader) { // old value is empty, but newVal is set
4547 return true;
4548 }
4549 }
4550
4551 return false;
4552}
4553
4554// Remove an entry from Vary header, if it exists
4555void RemoveFromVary(nsHttpResponseHead* aResponseHead,
4556 const nsACString& aRemove) {
4557 nsAutoCString buf;
4558 (void)aResponseHead->GetHeader(nsHttp::Vary, buf);
4559
4560 bool remove = false;
4561 for (const nsACString& token :
4562 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4563 if (token.EqualsIgnoreCase(aRemove)) {
4564 // Need to build a new string without aRemove
4565 remove = true;
4566 break;
4567 }
4568 }
4569 if (!remove) {
4570 return;
4571 }
4572 nsAutoCString newValue;
4573 for (const nsACString& token :
4574 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4575 if (!token.EqualsIgnoreCase(aRemove)) {
4576 if (!newValue.IsEmpty()) {
4577 newValue += ","_ns;
4578 }
4579 newValue += token;
4580 }
4581 }
4582 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)
4583 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)
;
4584 (void)aResponseHead->SetHeaderOverride(nsHttp::Vary, newValue);
4585}
4586
4587// We need to have an implementation of this function just so that we can keep
4588// all references to mCallOnResume of type nsHttpChannel: it's not OK in C++
4589// to set a member function ptr to a base class function.
4590void nsHttpChannel::HandleAsyncAbort() {
4591 HttpAsyncAborter<nsHttpChannel>::HandleAsyncAbort();
4592}
4593
4594//-----------------------------------------------------------------------------
4595// nsHttpChannel <byte-range>
4596//-----------------------------------------------------------------------------
4597
4598bool nsHttpChannel::IsResumable(int64_t partialLen, int64_t contentLength,
4599 bool ignoreMissingPartialLen) const {
4600 bool hasContentEncoding =
4601 mCachedResponseHead->HasHeader(nsHttp::Content_Encoding);
4602
4603 nsAutoCString etag;
4604 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, etag);
4605 bool hasWeakEtag = !etag.IsEmpty() && StringBeginsWith(etag, "W/"_ns);
4606
4607 return (partialLen < contentLength) &&
4608 (partialLen > 0 || ignoreMissingPartialLen) && !hasContentEncoding &&
4609 !hasWeakEtag && mCachedResponseHead->IsResumable() &&
4610 !LoadCustomConditionalRequest() && !mCachedResponseHead->NoStore();
4611}
4612
4613nsresult nsHttpChannel::MaybeSetupByteRangeRequest(
4614 int64_t partialLen, int64_t contentLength, bool ignoreMissingPartialLen) {
4615 // Be pesimistic
4616 StoreIsPartialRequest(false);
4617
4618 if (!IsResumable(partialLen, contentLength, ignoreMissingPartialLen)) {
4619 return NS_ERROR_NOT_RESUMABLE;
4620 }
4621
4622 // looks like a partial entry we can reuse; add If-Range
4623 // and Range headers.
4624 nsresult rv = SetupByteRangeRequest(partialLen);
4625 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4626 // Make the request unconditional again.
4627 UntieByteRangeRequest();
4628 }
4629
4630 return rv;
4631}
4632
4633nsresult nsHttpChannel::SetupByteRangeRequest(int64_t partialLen) {
4634 // cached content has been found to be partial, add necessary request
4635 // headers to complete cache entry.
4636
4637 // use strongest validator available...
4638 nsAutoCString val;
4639 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, val);
4640 if (val.IsEmpty()) {
4641 (void)mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
4642 }
4643 if (val.IsEmpty()) {
4644 // if we hit this code it means mCachedResponseHead->IsResumable() is
4645 // either broken or not being called.
4646 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"
, 4646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no cache validator" ")"); do { MOZ_CrashSequence
(__null, 4646); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4647 StoreIsPartialRequest(false);
4648 return NS_ERROR_FAILURE;
4649 }
4650
4651 char buf[64];
4652 SprintfLiteral(buf, "bytes=%" PRId64"l" "d" "-", partialLen);
4653
4654 DebugOnly<nsresult> rv{};
4655 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(buf));
4656 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"
, 4656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4656); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4657 rv = mRequestHead.SetHeader(nsHttp::If_Range, val);
4658 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"
, 4658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4658); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4659 StoreIsPartialRequest(true);
4660
4661 return NS_OK;
4662}
4663
4664void nsHttpChannel::UntieByteRangeRequest() {
4665 DebugOnly<nsresult> rv{};
4666 rv = mRequestHead.ClearHeader(nsHttp::Range);
4667 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"
, 4667); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4667); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4668 rv = mRequestHead.ClearHeader(nsHttp::If_Range);
4669 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"
, 4669); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4669); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4670}
4671
4672nsresult nsHttpChannel::ProcessPartialContent(
4673 const std::function<nsresult(nsHttpChannel*, nsresult)>&
4674 aContinueProcessResponseFunc) {
4675 // ok, we've just received a 206
4676 //
4677 // we need to stream whatever data is in the cache out first, and then
4678 // pick up whatever data is on the wire, writing it into the cache.
4679
4680 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)
;
4681
4682 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"
, 4682); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4683 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"
, 4683); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4684
4685 // Check if the content-encoding we now got is different from the one we
4686 // got before
4687 nsAutoCString contentEncoding, cachedContentEncoding;
4688 // It is possible that there is not such headers
4689 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
4690 (void)mCachedResponseHead->GetHeader(nsHttp::Content_Encoding,
4691 cachedContentEncoding);
4692 if (nsCRT::strcasecmp(contentEncoding.get(), cachedContentEncoding.get()) !=
4693 0) {
4694 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
4695 return CallOnStartRequest();
4696 }
4697
4698 nsresult rv;
4699
4700 int64_t cachedContentLength = mCachedResponseHead->ContentLength();
4701 int64_t entitySize = mResponseHead->TotalEntitySize();
4702
4703 nsAutoCString contentRange;
4704 (void)mResponseHead->GetHeader(nsHttp::Content_Range, contentRange);
4705 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)
4706 ("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)
4707 "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)
4708 ", 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)
4709 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)
4710 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)
;
4711
4712 if ((entitySize >= 0) && (cachedContentLength >= 0) &&
4713 (entitySize != cachedContentLength)) {
4714 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)
4715 ("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)
4716 "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)
4717 "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)
4718 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
4719
4720 mCacheEntry->AsyncDoom(nullptr);
4721 Cancel(NS_ERROR_CORRUPTED_CONTENT);
4722 return CallOnStartRequest();
4723 }
4724
4725 if (LoadConcurrentCacheAccess()) {
4726 // We started to read cached data sooner than its write has been done.
4727 // But the concurrent write has not finished completely, so we had to
4728 // do a range request. Now let the content coming from the network
4729 // be presented to consumers and also stored to the cache entry.
4730
4731 rv = InstallCacheListener(mLogicalOffset);
4732 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4733 } else {
4734 // suspend the current transaction
4735 rv = mTransactionPump->Suspend();
4736 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4737 }
4738
4739 // merge any new headers with the cached response headers
4740 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
4741
4742 // update the cached response head
4743 nsAutoCString head;
4744 mCachedResponseHead->Flatten(head, true);
4745 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
4746 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4747
4748 // make the cached response be the current response
4749 mResponseHead = std::move(mCachedResponseHead);
4750
4751 UpdateInhibitPersistentCachingFlag();
4752
4753 rv = UpdateExpirationTime();
4754 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4755
4756 // notify observers interested in looking at a response that has been
4757 // merged with any cached headers (http-on-examine-merged-response).
4758 gHttpHandler->OnExamineMergedResponse(this);
4759
4760 if (LoadConcurrentCacheAccess()) {
4761 StoreCachedContentIsPartial(false);
4762 // Leave the ConcurrentCacheAccess flag set, we want to use it
4763 // to prevent duplicate OnStartRequest call on the target listener
4764 // in case this channel is canceled before it gets its OnStartRequest
4765 // from the http transaction.
4766 return rv;
4767 }
4768
4769 // Now we continue reading the network response.
4770 // the cached content is valid, although incomplete.
4771 StoreCachedContentIsValid(CachedContentValidity::Valid);
4772 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
4773 nsresult rv = self->ReadFromCache();
4774 return aContinueProcessResponseFunc(self, rv);
4775 });
4776}
4777
4778nsresult nsHttpChannel::OnDoneReadingPartialCacheEntry(bool* streamDone) {
4779 nsresult rv;
4780
4781 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)
;
4782
4783 // by default, assume we would have streamed all data or failed...
4784 *streamDone = true;
4785
4786 // setup cache listener to append to cache entry
4787 int64_t size;
4788 rv = mCacheEntry->GetDataSize(&size);
4789 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4790
4791 rv = InstallCacheListener(size);
4792 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4793
4794 // Entry is valid, do it now, after the output stream has been opened,
4795 // otherwise when done earlier, pending readers would consider the cache
4796 // entry still as partial (CacheEntry::GetDataSize would return the partial
4797 // data size) and consumers would do the conditional request again.
4798 rv = mCacheEntry->SetValid();
4799 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4800
4801 // need to track the logical offset of the data being sent to our listener
4802 mLogicalOffset = size;
4803
4804 // we're now completing the cached content, so we can clear this flag.
4805 // this puts us in the state of a regular download.
4806 StoreCachedContentIsPartial(false);
4807 // The cache input stream pump is finished, we do not need it any more.
4808 // (see bug 1313923)
4809 mCachePump = nullptr;
4810
4811 // resume the transaction if it exists, otherwise the pipe contained the
4812 // remaining part of the document and we've now streamed all of the data.
4813 if (mTransactionPump) {
4814 rv = mTransactionPump->Resume();
4815 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) *streamDone = false;
4816 } else {
4817 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"
, 4817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no transaction" ")"); do { MOZ_CrashSequence
(__null, 4817); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4818 }
4819 return rv;
4820}
4821
4822//-----------------------------------------------------------------------------
4823// nsHttpChannel <cache>
4824//-----------------------------------------------------------------------------
4825
4826bool nsHttpChannel::ShouldBypassProcessNotModified() {
4827 if (LoadCustomConditionalRequest()) {
4828 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)
;
4829 return true;
4830 }
4831
4832 if (!mDidReval) {
4833 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)
4834 ("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)
4835 "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)
;
4836 return true;
4837 }
4838
4839 return false;
4840}
4841
4842void nsHttpChannel::MaybeGenerateNELReport() {
4843 if (!StaticPrefs::network_http_network_error_logging_enabled()) {
4844 return;
4845 }
4846
4847 nsCOMPtr<nsINetworkErrorReport> report;
4848 if (nsCOMPtr<nsINetworkErrorLogging> nel =
4849 components::NetworkErrorLogging::Service()) {
4850 nel->GenerateNELReport(this, getter_AddRefs(report));
4851 }
4852
4853 mReportedNEL = true;
4854
4855 // https://www.w3.org/TR/2023/WD-network-error-logging-20231005/#deliver-a-network-report
4856 // 4. Generate a network report given these parameters:
4857 // type: network-error
4858 // url
4859 // user_agent
4860 // body
4861
4862 if (!report) {
4863 return;
4864 }
4865
4866 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
4867 if (!ssm) {
4868 return;
4869 }
4870
4871 nsCOMPtr<nsIPrincipal> channelPrincipal;
4872 ssm->GetChannelResultPrincipal(this, getter_AddRefs(channelPrincipal));
4873 if (!channelPrincipal) {
4874 return;
4875 }
4876
4877 nsAutoCString body;
4878 nsAutoString group;
4879 nsAutoString url;
4880
4881 report->GetBody(body);
4882 report->GetGroup(group);
4883 report->GetUrl(url);
4884
4885 nsAutoCString endpointURL;
4886 ReportingHeader::GetEndpointForReportIncludeSubdomains(
4887 NS_ConvertUTF16toUTF8(group), channelPrincipal,
4888 /* includeSubdomains */ true, endpointURL);
4889 if (endpointURL.IsEmpty()) {
4890 return;
4891 }
4892
4893 ReportDeliver::ReportData data;
4894 data.mType = "network-error"_ns;
4895 data.mGroupName = NS_ConvertUTF16toUTF8(group);
4896 data.mURL = NS_ConvertUTF16toUTF8(url);
4897 data.mFailures = 0;
4898 data.mCreationTime = TimeStamp::Now();
4899
4900 data.mPrincipal = std::move(channelPrincipal);
4901 data.mEndpointURL = std::move(endpointURL);
4902 data.mReportBodyJSON = std::move(body);
4903 nsAutoCString userAgent;
4904 // XXX(valentin): Should this be the potentially user set value of the header
4905 // or the current value of user_agent from http handler?
4906 (void)mRequestHead.GetHeader(nsHttp::User_Agent, userAgent);
4907 data.mUserAgent = std::move(userAgent);
4908
4909 // Enqueue the report to be delivered by the reporting API
4910 ReportDeliver::Fetch(data);
4911}
4912
4913nsresult nsHttpChannel::ProcessNotModified(
4914 const std::function<nsresult(nsHttpChannel*, nsresult)>&
4915 aContinueProcessResponseFunc) {
4916 nsresult rv;
4917
4918 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)
;
4919
4920 // Assert ShouldBypassProcessNotModified() has been checked before call to
4921 // ProcessNotModified().
4922 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"
, 4922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ShouldBypassProcessNotModified()"
")"); do { MOZ_CrashSequence(__null, 4922); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4923
4924 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", 4924
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedResponseHead"
")"); do { MOZ_CrashSequence(__null, 4924); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4925 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"
, 4925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 4925); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4926 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", 4926
); return NS_ERROR_UNEXPECTED; } } while (false)
;
4927
4928 // If the 304 response contains a Last-Modified different than the
4929 // one in our cache that is pretty suspicious and is, in at least the
4930 // case of bug 716840, a sign of the server having previously corrupted
4931 // our cache with a bad response. Take the minor step here of just dooming
4932 // that cache entry so there is a fighting chance of getting things on the
4933 // right track.
4934
4935 nsAutoCString lastModifiedCached;
4936 nsAutoCString lastModified304;
4937
4938 rv =
4939 mCachedResponseHead->GetHeader(nsHttp::Last_Modified, lastModifiedCached);
4940 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4941 rv = mResponseHead->GetHeader(nsHttp::Last_Modified, lastModified304);
4942 }
4943
4944 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !lastModified304.Equals(lastModifiedCached)) {
4945 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)
4946 ("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)
4947 "[%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)
4948 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)
;
4949
4950 mCacheEntry->AsyncDoom(nullptr);
4951 glean::http::cache_lm_inconsistent
4952 .EnumGet(glean::http::CacheLmInconsistentLabel::eTrue)
4953 .Add();
4954 }
4955
4956 // merge any new headers with the cached response headers
4957 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
4958
4959 // update the cached response head
4960 nsAutoCString head;
4961 mCachedResponseHead->Flatten(head, true);
4962 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
4963 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4964
4965 if (LoadUsedNetwork() && !mReportedNEL) {
4966 MaybeGenerateNELReport();
4967 }
4968
4969 // make the cached response be the current response
4970 mResponseHead = std::move(mCachedResponseHead);
4971
4972 UpdateInhibitPersistentCachingFlag();
4973
4974 rv = UpdateExpirationTime();
4975 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4976
4977 rv = AddCacheEntryHeaders(mCacheEntry, false);
4978 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4979
4980 // notify observers interested in looking at a reponse that has been
4981 // merged with any cached headers
4982 gHttpHandler->OnExamineMergedResponse(this);
4983
4984 StoreCachedContentIsValid(CachedContentValidity::Valid);
4985
4986 // Tell other consumers the entry is OK to use
4987 rv = mCacheEntry->SetValid();
4988 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4989
4990 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
4991 nsresult rv = self->ReadFromCache();
4992 return aContinueProcessResponseFunc(self, rv);
4993 });
4994}
4995
4996// Determines if a request is a byte range request for a subrange,
4997// i.e. is a byte range request, but not a 0- byte range request.
4998static bool IsSubRangeRequest(nsHttpRequestHead& aRequestHead) {
4999 nsAutoCString byteRange;
5000 if (NS_FAILED(aRequestHead.GetHeader(nsHttp::Range, byteRange))((bool)(__builtin_expect(!!(NS_FAILED_impl(aRequestHead.GetHeader
(nsHttp::Range, byteRange))), 0)))
) {
5001 return false;
5002 }
5003
5004 if (byteRange.EqualsLiteral("bytes=0-")) {
5005#ifndef ANDROID
5006 glean::network::byte_range_request.Get("cacheable"_ns).Add(1);
5007#endif
5008 return false;
5009 }
5010#ifndef ANDROID
5011 glean::network::byte_range_request.Get("not_cacheable"_ns).Add(1);
5012#endif
5013 return true;
5014}
5015
5016nsresult nsHttpChannel::OpenCacheEntry(bool isHttps) {
5017 // Drop this flag here
5018 StoreConcurrentCacheAccess(0);
5019
5020 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)
;
5021
5022 // make sure we're not abusing this function
5023 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"
, 5023); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheEntry"
") (" "cache entry already open" ")"); do { MOZ_CrashSequence
(__null, 5023); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5024 if (!mRequestHead.IsGet() && !mRequestHead.IsHead() &&
5025 !mRequestHead.IsPost() && !mRequestHead.IsPatch()) {
5026 // don't use the cache for other types of requests
5027 return NS_OK;
5028 }
5029
5030 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", 5030
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPostID > 0" ")"
); do { MOZ_CrashSequence(__null, 5030); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5031
5032 return OpenCacheEntryInternal(isHttps);
5033}
5034
5035nsresult nsHttpChannel::OpenCacheEntryInternal(bool isHttps) {
5036 nsresult rv;
5037
5038 if (LoadResuming()) {
5039 // We don't support caching for requests initiated
5040 // via nsIResumableChannel.
5041 return NS_OK;
5042 }
5043
5044 // Don't cache byte range requests which are subranges, only cache 0-
5045 // byte range requests.
5046 if (IsSubRangeRequest(mRequestHead)) {
5047 return NS_OK;
5048 }
5049
5050 // Handle correctly WaitForCacheEntry
5051 AutoCacheWaitFlags waitFlags(this);
5052
5053 nsAutoCString cacheKey;
5054
5055 nsCOMPtr<nsICacheStorage> cacheStorage;
5056 mCacheEntryURI = mURI;
5057
5058 uint32_t cacheEntryOpenFlags;
5059 bool offline = gIOService->IsOffline();
5060
5061 nsAutoCString cacheControlRequestHeader;
5062 (void)mRequestHead.GetHeader(nsHttp::Cache_Control,
5063 cacheControlRequestHeader);
5064 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
5065 if (cacheControlRequest.NoStore()) {
5066 return NS_OK;
5067 }
5068
5069 bool forceOffline = IsForcedOffline();
5070 if (offline || (mLoadFlags & INHIBIT_CACHING) || forceOffline) {
5071 if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
&&
5072 !offline && !forceOffline) {
5073 return NS_OK;
5074 }
5075 cacheEntryOpenFlags = nsICacheStorage::OPEN_READONLY;
5076 StoreCacheEntryIsReadOnly(true);
5077 } else if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
5078 cacheEntryOpenFlags = nsICacheStorage::OPEN_TRUNCATE;
5079 } else {
5080 cacheEntryOpenFlags =
5081 nsICacheStorage::OPEN_NORMALLY | nsICacheStorage::CHECK_MULTITHREADED;
5082 }
5083
5084 // Remember the request is a custom conditional request so that we can
5085 // process any 304 response correctly.
5086 StoreCustomConditionalRequest(
5087 mRequestHead.HasHeader(nsHttp::If_Modified_Since) ||
5088 mRequestHead.HasHeader(nsHttp::If_None_Match) ||
5089 mRequestHead.HasHeader(nsHttp::If_Unmodified_Since) ||
5090 mRequestHead.HasHeader(nsHttp::If_Match) ||
5091 mRequestHead.HasHeader(nsHttp::If_Range));
5092
5093 rv = GetCacheStorage(getter_AddRefs(cacheStorage));
5094 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"
, 5094); return rv; } } while (false)
;
5095
5096 if ((mClassOfService.Flags() & nsIClassOfService::Leader) ||
5097 (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)) {
5098 cacheEntryOpenFlags |= nsICacheStorage::OPEN_PRIORITY;
5099 }
5100
5101 // Only for backward compatibility with the old cache back end.
5102 // When removed, remove the flags and related code snippets.
5103 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
5104 cacheEntryOpenFlags |= nsICacheStorage::OPEN_BYPASS_IF_BUSY;
5105 }
5106
5107 if (mPostID) {
5108 mCacheIdExtension.AppendInt(mPostID);
5109 }
5110 if (LoadIsTRRServiceChannel()) {
5111 mCacheIdExtension.Append("TRR");
5112 }
5113 if (mRequestHead.IsHead()) {
5114 mCacheIdExtension.Append("HEAD");
5115 }
5116 bool isThirdParty = false;
5117 if (StaticPrefs::network_fetch_cache_partition_cross_origin() &&
5118 (NS_FAILED(mLoadInfo->TriggeringPrincipal()->IsThirdPartyChannel(((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
5119 this, &isThirdParty))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
||
5120 isThirdParty) &&
5121 (mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_FETCH ||
5122 mLoadInfo->InternalContentPolicyType() ==
5123 nsIContentPolicy::TYPE_XMLHTTPREQUEST ||
5124 mLoadInfo->InternalContentPolicyType() ==
5125 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_ASYNC ||
5126 mLoadInfo->InternalContentPolicyType() ==
5127 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_SYNC)) {
5128 mCacheIdExtension.Append("FETCH");
5129 }
5130
5131 mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY;
5132 mCacheQueueSizeWhenOpen =
5133 CacheStorageService::CacheQueueSize(mCacheOpenWithPriority);
5134
5135 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"
, 5135); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 5135); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5136 rv = cacheStorage->AsyncOpenURI(mCacheEntryURI, mCacheIdExtension,
5137 cacheEntryOpenFlags, this);
5138 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"
, 5138); return rv; } } while (false)
;
5139
5140 waitFlags.Keep(WAIT_FOR_CACHE_ENTRY);
5141
5142 return NS_OK;
5143}
5144
5145// We asked the cache for mCacheEntryURI, but the entry we got back may be
5146// stored under a different URL: on an exact-key miss the cache falls back to a
5147// No-Vary-Search secondary lookup, which can return a sibling entry whose URL
5148// is equivalent to ours under its No-Vary-Search header. Record which of the
5149// two happened, so that later code can tell whether the entry it holds is
5150// really ours to write to.
5151void nsHttpChannel::NoteCacheEntryKeyMatch(nsICacheEntry* aEntry) {
5152 StoreCacheEntryIsNoVarySearchMatch(false);
5153
5154 if (!aEntry || !mCacheEntryURI) {
5155 return;
5156 }
5157
5158 // Normalize the same way CacheStorage::AsyncOpenURI did to build the key.
5159 nsCOMPtr<nsIURI> noRefURI;
5160 nsAutoCString spec;
5161 if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetURIWithoutRef
(mCacheEntryURI, getter_AddRefs(noRefURI)))), 0)))
5162 NS_GetURIWithoutRef(mCacheEntryURI, getter_AddRefs(noRefURI)))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetURIWithoutRef
(mCacheEntryURI, getter_AddRefs(noRefURI)))), 0)))
||
5163 NS_FAILED(noRefURI->GetAsciiSpec(spec))((bool)(__builtin_expect(!!(NS_FAILED_impl(noRefURI->GetAsciiSpec
(spec))), 0)))
) {
5164 return;
5165 }
5166
5167 nsAutoCString key;
5168 if (NS_FAILED(aEntry->GetKey(key))((bool)(__builtin_expect(!!(NS_FAILED_impl(aEntry->GetKey(
key))), 0)))
) {
5169 return;
5170 }
5171
5172 if (!key.Equals(spec)) {
5173 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)
5174 ("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)
5175 "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)
5176 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)
;
5177 StoreCacheEntryIsNoVarySearchMatch(true);
5178 }
5179}
5180
5181// Picks the storage matching the channel's persistence flags as they stand
5182// right now. Called both when first opening the entry and when replacing an
5183// alias entry later, by which point a no-store response may have set
5184// INHIBIT_PERSISTENT_CACHING and the replacement must be memory-only.
5185nsresult nsHttpChannel::GetCacheStorage(nsICacheStorage** aStorage) {
5186 nsCOMPtr<nsICacheStorageService> service(components::CacheStorage::Service());
5187 if (!service) {
5188 return NS_ERROR_NOT_AVAILABLE;
5189 }
5190
5191 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
5192 if (!info) {
5193 return NS_ERROR_FAILURE;
5194 }
5195
5196 if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
5197 return service->MemoryCacheStorage(info, // ? choose app cache as well...
5198 aStorage);
5199 }
5200 if (LoadPinCacheContent()) {
5201 return service->PinningCacheStorage(info, aStorage);
5202 }
5203 return service->DiskCacheStorage(info, aStorage);
5204}
5205
5206// Called before anything is written to mCacheEntry. When the entry we hold was
5207// found through No-Vary-Search it is stored under a different URL, and this
5208// response describes mCacheEntryURI only, so writing to it would put our
5209// content under someone else's key. Open a fresh entry of our own instead.
5210// Releasing the last handle on the borrowed entry reverts it from REVALIDATING
5211// back to READY, leaving its own representation untouched.
5212nsresult nsHttpChannel::MaybeReplaceNoVarySearchAliasEntry() {
5213 if (!LoadCacheEntryIsNoVarySearchMatch() || !mCacheEntry ||
5214 LoadCacheEntryIsReadOnly()) {
5215 return NS_OK;
5216 }
5217
5218 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)
;
5219
5220 nsCOMPtr<nsICacheStorage> storage;
5221 nsresult rv = GetCacheStorage(getter_AddRefs(storage));
5222 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5223 rv = storage->OpenTruncate(mCacheEntryURI, mCacheIdExtension,
5224 getter_AddRefs(mCacheEntry));
5225 }
5226
5227 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5228 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)
5229 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)
;
5230 mCacheEntry = nullptr;
5231 return rv;
5232 }
5233
5234 // We now hold an entry keyed on mCacheEntryURI, so it is ours to write to.
5235 StoreCacheEntryIsNoVarySearchMatch(false);
5236 StoreCacheEntryIsWriteOnly(true);
5237 // The alt-data belonged to the entry we just let go of.
5238 mAvailableCachedAltDataType.Truncate();
5239 StoreDeliveringAltData(false);
5240
5241 return NS_OK;
5242}
5243
5244nsresult nsHttpChannel::CheckPartial(nsICacheEntry* aEntry, int64_t* aSize,
5245 int64_t* aContentLength) {
5246 return nsHttp::CheckPartial(
5247 aEntry, aSize, aContentLength,
5248 mCachedResponseHead ? mCachedResponseHead.get() : mResponseHead.get());
5249}
5250
5251void nsHttpChannel::UntieValidationRequest() {
5252 DebugOnly<nsresult> rv{};
5253 // Make the request unconditional again.
5254 rv = mRequestHead.ClearHeader(nsHttp::If_Modified_Since);
5255 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"
, 5255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5255); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5256 rv = mRequestHead.ClearHeader(nsHttp::If_None_Match);
5257 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"
, 5257); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5257); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5258 rv = mRequestHead.ClearHeader(nsHttp::ETag);
5259 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"
, 5259); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5259); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5260}
5261
5262NS_IMETHODIMPnsresult
5263nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, uint32_t* aResult) {
5264 nsresult rv = NS_OK;
5265
5266 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnCacheEntryCheck", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject5267( "nsHttpChannel::OnCacheEntryCheck"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
5267 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject5267( "nsHttpChannel::OnCacheEntryCheck"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
5268 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)
5269 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)
;
5270
5271 if (mCacheWaitTimedOut) {
5272 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)
;
5273 *aResult = ENTRY_NOT_WANTED;
5274 return NS_OK;
5275 }
5276
5277 NoteCacheEntryKeyMatch(entry);
5278
5279 nsAutoCString cacheControlRequestHeader;
5280 (void)mRequestHead.GetHeader(nsHttp::Cache_Control,
5281 cacheControlRequestHeader);
5282 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
5283
5284 if (cacheControlRequest.NoStore()) {
5285 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)
5286 ("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)
5287 "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)
;
5288 *aResult = ENTRY_NOT_WANTED;
5289 return NS_OK;
5290 }
5291
5292 // Be pessimistic: assume the cache entry has no useful data.
5293 *aResult = ENTRY_WANTED;
5294 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5295
5296 nsCString buf;
5297
5298 // Get the method that was used to generate the cached response
5299 rv = entry->GetMetaDataElement("request-method", getter_Copies(buf));
5300 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"
, 5300); return rv; } } while (false)
;
5301
5302 bool methodWasHead = buf.EqualsLiteral("HEAD");
5303 bool methodWasGet = buf.EqualsLiteral("GET");
5304
5305 if (methodWasHead) {
5306 // The cached response does not contain an entity. We can only reuse
5307 // the response if the current request is also HEAD.
5308 if (!mRequestHead.IsHead()) {
5309 *aResult = ENTRY_NOT_WANTED;
5310 return NS_OK;
5311 }
5312 }
5313 buf.Adopt(nullptr);
5314
5315 // We'll need this value in later computations...
5316 uint32_t lastModifiedTime;
5317 rv = entry->GetLastModified(&lastModifiedTime);
5318 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5318); return rv; } } while (false)
;
5319
5320 // Determine if this is the first time that this cache entry
5321 // has been accessed during this session.
5322 bool fromPreviousSession =
5323 (gHttpHandler->SessionStartTime() > lastModifiedTime);
5324
5325 // Get the cached HTTP response headers
5326 mCachedResponseHead = MakeUnique<nsHttpResponseHead>();
5327
5328 rv = nsHttp::GetHttpResponseHeadFromCacheEntry(entry,
5329 mCachedResponseHead.get());
5330 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"
, 5330); return rv; } } while (false)
;
5331
5332 // Purge stale cache entries that have dcb/dcz Content-Encoding in their
5333 // metadata. These were written by early compression dictionary code that
5334 // failed to clear Content-Encoding before writing cache metadata. The data
5335 // body is decompressed but the header is wrong; serving such entries would
5336 // cause crashes in content processes. Doom and re-fetch from network.
5337 {
5338 nsAutoCString cachedEncoding;
5339 (void)mCachedResponseHead->GetHeader(nsHttp::Content_Encoding,
5340 cachedEncoding);
5341 if (cachedEncoding.LowerCaseFindASCII("dcb") != -1 ||
5342 cachedEncoding.LowerCaseFindASCII("dcz") != -1) {
5343 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)
5344 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)
;
5345 glean::http3::stale_dcb_dcz_cache_entries_purged.Add(1);
5346 entry->AsyncDoom(nullptr);
5347 *aResult = ENTRY_NOT_WANTED;
5348 return NS_OK;
5349 }
5350 }
5351
5352 bool isCachedRedirect = WillRedirect(*mCachedResponseHead);
5353
5354 // Do not return 304 responses from the cache, and also do not return
5355 // any other non-redirect 3xx responses from the cache (see bug 759043).
5356 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"
, 5357); return NS_ERROR_ABORT; } } while (false)
5357 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"
, 5357); return NS_ERROR_ABORT; } } while (false)
;
5358
5359 if (mCachedResponseHead->NoStore() && LoadCacheEntryIsReadOnly()) {
5360 // This prevents loading no-store responses when navigating back
5361 // while the browser is set to work offline.
5362 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)
;
5363 mLoadFlags |= nsIRequest::INHIBIT_CACHING;
5364 }
5365
5366 // Don't bother to validate items that are read-only,
5367 // unless they are read-only because of INHIBIT_CACHING
5368 if ((LoadCacheEntryIsReadOnly() &&
5369 !(mLoadFlags & nsIRequest::INHIBIT_CACHING))) {
5370 int64_t size, contentLength;
5371 rv = CheckPartial(entry, &size, &contentLength);
5372 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"
, 5372); return rv; } } while (false)
;
5373
5374 if (contentLength != int64_t(-1) && contentLength != size) {
5375 *aResult = ENTRY_NOT_WANTED;
5376 return NS_OK;
5377 }
5378
5379 rv = OpenCacheInputStream(entry, true);
5380 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5381 StoreCachedContentIsValid(CachedContentValidity::Valid);
5382 }
5383 return rv;
5384 }
5385
5386 bool wantCompleteEntry = false;
5387
5388 if (!methodWasHead && !isCachedRedirect) {
5389 // If the cached content-length is set and it does not match the data
5390 // size of the cached content, then the cached response is partial...
5391 // either we need to issue a byte range request or we need to refetch
5392 // the entire document.
5393 //
5394 // We exclude redirects from this check because we (usually) strip the
5395 // entity when we store the cache entry, and even if we didn't, we
5396 // always ignore a cached redirect's entity anyway. See bug 759043.
5397 int64_t size, contentLength;
5398 rv = CheckPartial(entry, &size, &contentLength);
5399 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"
, 5399); return rv; } } while (false)
;
5400
5401 if (LoadCacheEntryIsNoVarySearchMatch() &&
5402 (size == int64_t(-1) ||
5403 (contentLength != int64_t(-1) && contentLength != size))) {
5404 // Completing this entry means appending our bytes to content stored
5405 // under a different URL, and unlike a full response we cannot divert
5406 // that to an entry of our own: the range request only makes sense
5407 // against what is already there. Refetch from scratch instead.
5408 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)
;
5409 *aResult = ENTRY_NOT_WANTED;
5410 return NS_OK;
5411 }
5412
5413 if (size == int64_t(-1)) {
5414 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)
;
5415 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
5416 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)
5417 (" 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)
5418 "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)
;
5419
5420 *aResult = ENTRY_NOT_WANTED;
5421 return NS_OK;
5422 }
5423
5424 // Ignore !(size > 0) from the resumability condition
5425 if (!IsResumable(size, contentLength, true)) {
5426 if (IsNavigation()) {
5427 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)
5428 (" 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)
5429 "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)
;
5430 *aResult = ENTRY_NOT_WANTED;
5431 return NS_OK;
5432 }
5433
5434 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)
5435 (" 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)
5436 "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)
;
5437
5438 wantCompleteEntry = true;
5439 } else {
5440 StoreConcurrentCacheAccess(1);
5441 }
5442 } else if (contentLength != int64_t(-1) && contentLength != size) {
5443 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)
5444 ("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)
5445 "[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)
5446 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)
;
5447
5448 rv = MaybeSetupByteRangeRequest(size, contentLength);
5449 StoreCachedContentIsPartial(NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest());
5450 if (LoadCachedContentIsPartial()) {
5451 rv = OpenCacheInputStream(entry, false);
5452 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5453 UntieByteRangeRequest();
5454 return rv;
5455 }
5456
5457 *aResult = ENTRY_NEEDS_REVALIDATION;
5458 return NS_OK;
5459 }
5460
5461 if (size == 0 && LoadCacheOnlyMetadata()) {
5462 // Don't break cache entry load when the entry's data size
5463 // is 0 and CacheOnlyMetadata flag is set. In that case we
5464 // want to proceed since the LOAD_ONLY_IF_MODIFIED flag is
5465 // also set.
5466 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", 5466
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadFlags & LOAD_ONLY_IF_MODIFIED"
")"); do { MOZ_CrashSequence(__null, 5466); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5467 } else {
5468 return rv;
5469 }
5470 }
5471 }
5472
5473 bool isHttps = mURI->SchemeIs("https");
5474
5475 bool doValidation = false;
5476 bool doBackgroundValidation = false;
5477 bool canAddImsHeader = true;
5478
5479 bool isForcedValid = false;
5480 entry->GetIsForcedValid(&isForcedValid);
5481
5482 bool weaklyFramed, isImmutable;
5483 nsHttp::DetermineFramingAndImmutability(entry, mCachedResponseHead.get(),
5484 isHttps, &weaklyFramed, &isImmutable);
5485
5486 // Cached entry is not the entity we request (see bug #633743)
5487 if (ResponseWouldVary(entry)) {
5488 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)
;
5489 canAddImsHeader = false;
5490 doValidation = true;
5491 } else {
5492 if (mCachedResponseHead->ExpiresInPast() ||
5493 mCachedResponseHead->MustValidateIfExpired()) {
5494 }
5495 doValidation = nsHttp::ValidationRequired(
5496 isForcedValid, mCachedResponseHead.get(), mLoadFlags,
5497 LoadAllowStaleCacheContent(), LoadForceValidateCacheContent(),
5498 isImmutable, LoadCustomConditionalRequest(), mRequestHead, entry,
5499 cacheControlRequest, fromPreviousSession, &doBackgroundValidation);
5500
5501 // A navigation activated from a completed speculation-rules prefetch record
5502 // must serve the prefetched response as-is (spec: "create navigation params
5503 // from a prefetch record"), so skip freshness/no-store revalidation of the
5504 // entry we just found.
5505 if (doValidation && mLoadInfo->GetActivatedFromNavigationalPrefetch()) {
5506 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " serving speculation-rules prefetch from cache without " "validation"
); } } while (0)
5507 (" serving speculation-rules prefetch from cache without "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " serving speculation-rules prefetch from cache without " "validation"
); } } while (0)
5508 "validation"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " serving speculation-rules prefetch from cache without " "validation"
); } } while (0)
;
5509 doValidation = false;
5510 }
5511 }
5512
5513 nsAutoCString requestedETag;
5514 if (!doValidation &&
5515 NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::If_Match, requestedETag))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::If_Match, requestedETag))), 1)))
&&
5516 (methodWasGet || methodWasHead)) {
5517 nsAutoCString cachedETag;
5518 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, cachedETag);
5519 if (!cachedETag.IsEmpty() && (StringBeginsWith(cachedETag, "W/"_ns) ||
5520 !requestedETag.Equals(cachedETag))) {
5521 // User has defined If-Match header, if the cached entry is not
5522 // matching the provided header value or the cached ETag is weak,
5523 // force validation.
5524 doValidation = true;
5525 }
5526 }
5527
5528 // Previous error should not be propagated.
5529 rv = NS_OK;
5530
5531 if (!doValidation) {
5532 //
5533 // Check the authorization headers used to generate the cache entry.
5534 // We must validate the cache entry if:
5535 //
5536 // 1) the cache entry was generated prior to this session w/
5537 // credentials (see bug 103402).
5538 // 2) the cache entry was generated w/o credentials, but would now
5539 // require credentials (see bug 96705).
5540 //
5541 // NOTE: this does not apply to proxy authentication.
5542 //
5543 entry->GetMetaDataElement("auth", getter_Copies(buf));
5544 doValidation =
5545 (fromPreviousSession && !buf.IsEmpty()) ||
5546 (buf.IsEmpty() && mRequestHead.HasHeader(nsHttp::Authorization));
5547 }
5548
5549 // Bug #561276: We maintain a chain of cache-keys which returns cached
5550 // 3xx-responses (redirects) in order to detect cycles. If a cycle is
5551 // found, ignore the cached response and hit the net. Otherwise, use
5552 // the cached response and add the cache-key to the chain. Note that
5553 // a limited number of redirects (cached or not) is allowed and is
5554 // enforced independently of this mechanism
5555 if (!doValidation && isCachedRedirect) {
5556 nsAutoCString cacheKey;
5557 rv = GenerateCacheKey(mPostID, cacheKey);
5558 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"
, 5558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5558); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5559
5560 auto redirectedCachekeys = mRedirectedCachekeys.Lock();
5561 auto& ref = redirectedCachekeys.ref();
5562 if (!ref) {
5563 ref = MakeUnique<nsTArray<nsCString>>();
5564 } else if (ref->Contains(cacheKey)) {
5565 doValidation = true;
5566 }
5567
5568 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)
5569 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)
;
5570
5571 // Append cacheKey if not in the chain already
5572 if (!doValidation) {
5573 ref->AppendElement(cacheKey);
5574 }
5575 }
5576
5577 StoreCachedContentIsValid(!doValidation ? CachedContentValidity::Valid
5578 : CachedContentValidity::Invalid);
5579
5580 if (isForcedValid) {
5581 // Telemetry value is only useful if this was a prefetched item
5582 if (!doValidation) {
5583 // Could have gotten to a funky state with some of the if chain above
5584 // and in nsHttp::ValidationRequired. Make sure we get it right here.
5585 entry->MarkForcedValidUse();
5586 }
5587 }
5588
5589 if (doValidation) {
5590 //
5591 // now, we are definitely going to issue a HTTP request to the server.
5592 // make it conditional if possible.
5593 //
5594 // do not attempt to validate no-store content, since servers will not
5595 // expect it to be cached. (we only keep it in our cache for the
5596 // purposes of back/forward, etc.)
5597 //
5598 // the request method MUST be either GET or HEAD (see bug 175641) and
5599 // the cached response code must be < 400
5600 //
5601 // the cached content must not be weakly framed
5602 //
5603 // do not override conditional headers when consumer has defined its own
5604 if (!mCachedResponseHead->NoStore() &&
5605 (mRequestHead.IsGet() || mRequestHead.IsHead()) &&
5606 !LoadCustomConditionalRequest() && !weaklyFramed &&
5607 (mCachedResponseHead->Status() < 400)) {
5608 if (LoadConcurrentCacheAccess()) {
5609 // In case of concurrent read and also validation request we
5610 // must wait for the current writer to close the output stream
5611 // first. Otherwise, when the writer's job would have been interrupted
5612 // before all the data were downloaded, we'd have to do a range request
5613 // which would be a second request in line during this channel's
5614 // life-time. nsHttpChannel is not designed to do that, so rather
5615 // turn off concurrent read and wait for entry's completion.
5616 // Then only re-validation or range-re-validation request will go out.
5617 StoreConcurrentCacheAccess(0);
5618 // This will cause that OnCacheEntryCheck is called again with the same
5619 // entry after the writer is done.
5620 wantCompleteEntry = true;
5621 } else {
5622 nsAutoCString val;
5623 // Add If-Modified-Since header if a Last-Modified was given
5624 // and we are allowed to do this (see bugs 510359 and 269303)
5625 if (canAddImsHeader) {
5626 (void)mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
5627 if (!val.IsEmpty()) {
5628 rv = mRequestHead.SetHeader(nsHttp::If_Modified_Since, val);
5629 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"
, 5629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5629); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5630 }
5631 }
5632 // Add If-None-Match header if an ETag was given in the response
5633 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, val);
5634 if (!val.IsEmpty()) {
5635 rv = mRequestHead.SetHeader(nsHttp::If_None_Match, val);
5636 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"
, 5636); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5637 }
5638 mDidReval = true;
5639 }
5640 }
5641 }
5642
5643 bool valid = CachedContentIsValid();
5644 if (valid || mDidReval) {
5645 rv = OpenCacheInputStream(entry, valid);
5646 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5647 // If we can't get the entity then we have to act as though we
5648 // don't have the cache entry.
5649 if (mDidReval) {
5650 UntieValidationRequest();
5651 mDidReval = false;
5652 }
5653 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5654 }
5655 }
5656
5657 if (mDidReval) {
5658 *aResult = ENTRY_NEEDS_REVALIDATION;
5659 } else if (wantCompleteEntry) {
5660 *aResult = RECHECK_AFTER_WRITE_FINISHED;
5661 } else {
5662 *aResult = ENTRY_WANTED;
5663
5664 if (doBackgroundValidation) {
5665 PerformBackgroundCacheRevalidation();
5666 }
5667 }
5668
5669 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)
5670 ("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)
5671 "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)
5672 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)
;
5673 return rv;
5674}
5675
5676NS_IMETHODIMPnsresult
5677nsHttpChannel::OnCacheEntryAvailable(nsICacheEntry* entry, bool aNew,
5678 nsresult status) {
5679 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", 5679
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 5679); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5680
5681 nsresult rv;
5682
5683 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnCacheEntryAvailable", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject5684( "nsHttpChannel::OnCacheEntryAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
5684 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject5684( "nsHttpChannel::OnCacheEntryAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
5685 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)
5686 ("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)
5687 "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)
5688 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)
;
5689
5690 // The cache callback arrived (or we're tearing down); the backstop timer is
5691 // no longer needed.
5692 CancelCacheWaitTimer();
5693
5694 // if the channel's already fired onStopRequest, then we should ignore
5695 // this event.
5696 if (!LoadIsPending()) {
5697 mCacheInputStream.CloseAndRelease();
5698 return NS_OK;
5699 }
5700
5701 // If the backstop already fired we gave up on the cache and raced to the
5702 // network; ignore this late callback so we don't reprocess the entry.
5703 if (mCacheWaitTimedOut) {
5704 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)
5705 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
5706 mCacheInputStream.CloseAndRelease();
5707 return NS_OK;
5708 }
5709
5710 rv = OnCacheEntryAvailableInternal(entry, aNew, status);
5711 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5712 CloseCacheEntry(false);
5713 (void)AsyncAbort(rv);
5714 }
5715
5716 return NS_OK;
5717}
5718
5719nsresult nsHttpChannel::OnCacheEntryAvailableInternal(nsICacheEntry* entry,
5720 bool aNew,
5721 nsresult status) {
5722 nsresult rv;
5723
5724 if (mCanceled) {
5725 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)
5726 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)
;
5727 return mStatus;
5728 }
5729
5730 rv = OnNormalCacheEntryAvailable(entry, aNew, status);
5731
5732 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
5733 return NS_ERROR_DOCUMENT_NOT_CACHED;
5734 }
5735
5736 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5737 return rv;
5738 }
5739
5740 // We may be waiting for more callbacks...
5741 if (AwaitingCacheCallbacks()) {
5742 return NS_OK;
5743 }
5744
5745 return TriggerNetwork();
5746}
5747
5748nsresult nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntry* aEntry,
5749 bool aNew,
5750 nsresult aEntryStatus) {
5751 StoreWaitForCacheEntry(LoadWaitForCacheEntry() & ~WAIT_FOR_CACHE_ENTRY);
5752
5753 if (NS_FAILED(aEntryStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aEntryStatus)), 0)
))
|| aNew) {
5754 // Make sure this flag is dropped. It may happen the entry is doomed
5755 // between OnCacheEntryCheck and OnCacheEntryAvailable.
5756 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5757
5758 // From the same reason remove any conditional headers added
5759 // in OnCacheEntryCheck.
5760 if (mDidReval) {
5761 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)
;
5762 UntieValidationRequest();
5763 mDidReval = false;
5764 }
5765
5766 if (LoadCachedContentIsPartial()) {
5767 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)
;
5768 UntieByteRangeRequest();
5769 StoreCachedContentIsPartial(false);
5770 }
5771
5772 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
5773 // if this channel is only allowed to pull from the cache, then
5774 // we must fail if we were unable to open a cache entry for read.
5775 return NS_ERROR_DOCUMENT_NOT_CACHED;
5776 }
5777 }
5778
5779 if (NS_SUCCEEDED(aEntryStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aEntryStatus)), 1
)))
) {
5780 mCacheEntry = aEntry;
5781 StoreCacheEntryIsWriteOnly(aNew);
5782 NoteCacheEntryKeyMatch(aEntry);
5783 }
5784
5785 return NS_OK;
5786}
5787
5788// Generates the proper cache-key for this instance of nsHttpChannel
5789nsresult nsHttpChannel::GenerateCacheKey(uint32_t postID,
5790 nsACString& cacheKey) {
5791 AssembleCacheKey(mSpec.get(), postID, cacheKey);
5792 return NS_OK;
5793}
5794
5795// Assembles a cache-key from the given pieces of information and |mLoadFlags|
5796void nsHttpChannel::AssembleCacheKey(const char* spec, uint32_t postID,
5797 nsACString& cacheKey) {
5798 cacheKey.Truncate();
5799
5800 if (mLoadFlags & LOAD_ANONYMOUS) {
5801 cacheKey.AssignLiteral("anon&");
5802 }
5803
5804 if (postID) {
5805 char buf[32];
5806 SprintfLiteral(buf, "id=%x&", postID);
5807 cacheKey.Append(buf);
5808 }
5809
5810 if (!cacheKey.IsEmpty()) {
5811 cacheKey.AppendLiteral("uri=");
5812 }
5813
5814 // Strip any trailing #ref from the URL before using it as the key
5815 const char* p = strchr(spec, '#');
5816 if (p) {
5817 cacheKey.Append(spec, p - spec);
5818 } else {
5819 cacheKey.Append(spec);
5820 }
5821}
5822
5823nsresult DoUpdateExpirationTime(nsHttpChannel* aSelf,
5824 nsICacheEntry* aCacheEntry,
5825 nsHttpResponseHead* aResponseHead,
5826 uint32_t& aExpirationTime) {
5827 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", 5827
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aExpirationTime == 0"
")"); do { MOZ_CrashSequence(__null, 5827); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5828 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"
, 5828); return NS_ERROR_FAILURE; } } while (false)
;
5829
5830 nsresult rv;
5831
5832 if (!aResponseHead->MustValidate()) {
5833 // For stale-while-revalidate we use expiration time as the absolute base
5834 // for calculation of the stale window absolute end time. Hence, when the
5835 // entry may be served w/o revalidation, we need a non-zero value for the
5836 // expiration time. Let's set it to |now|, which basicly means "expired",
5837 // same as when set to 0.
5838 uint32_t now = NowInSeconds()PRTimeToSeconds(PR_Now());
5839 aExpirationTime = now;
5840
5841 uint32_t freshnessLifetime = 0;
5842
5843 rv = aResponseHead->ComputeFreshnessLifetime(&freshnessLifetime);
5844 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5845
5846 if (freshnessLifetime > 0) {
5847 uint32_t currentAge = 0;
5848
5849 rv = aResponseHead->ComputeCurrentAge(now, aSelf->GetRequestTime(),
5850 &currentAge);
5851 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5852
5853 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)
5854 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)
;
5855
5856 if (freshnessLifetime > currentAge) {
5857 uint32_t timeRemaining = freshnessLifetime - currentAge;
5858 // be careful... now + timeRemaining may overflow
5859 if (now + timeRemaining < now) {
5860 aExpirationTime = uint32_t(-1);
5861 } else {
5862 aExpirationTime = now + timeRemaining;
5863 }
5864 }
5865 }
5866 }
5867
5868 rv = aCacheEntry->SetExpirationTime(aExpirationTime);
5869 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"
, 5869); return rv; } } while (false)
;
5870
5871 return rv;
5872}
5873
5874// UpdateExpirationTime is called when a new response comes in from the server.
5875// It updates the stored response-time and sets the expiration time on the
5876// cache entry.
5877//
5878// From section 13.2.4 of RFC2616, we compute expiration time as follows:
5879//
5880// timeRemaining = freshnessLifetime - currentAge
5881// expirationTime = now + timeRemaining
5882//
5883nsresult nsHttpChannel::UpdateExpirationTime() {
5884 uint32_t expirationTime = 0;
5885 nsresult rv = DoUpdateExpirationTime(this, mCacheEntry, mResponseHead.get(),
5886 expirationTime);
5887 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"
, 5887); return rv; } } while (false)
;
5888
5889 return NS_OK;
5890}
5891
5892nsresult nsHttpChannel::OpenCacheInputStream(nsICacheEntry* cacheEntry,
5893 bool startBuffering) {
5894 nsresult rv;
5895
5896 if (mURI->SchemeIs("https")) {
5897 rv = cacheEntry->GetSecurityInfo(getter_AddRefs(mCachedSecurityInfo));
5898 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5899 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)
5900 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)
;
5901 NS_WARNING("failed to parse security-info")NS_DebugBreak(NS_DEBUG_WARNING, "failed to parse security-info"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5901)
;
5902 cacheEntry->AsyncDoom(nullptr);
5903 return rv;
5904 }
5905
5906 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", 5906
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedSecurityInfo"
")"); do { MOZ_CrashSequence(__null, 5906); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5907 if (!mCachedSecurityInfo) {
5908 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)
5909 ("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)
5910 "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)
5911 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)
;
5912 cacheEntry->AsyncDoom(nullptr);
5913 return NS_ERROR_UNEXPECTED; // XXX error code
5914 }
5915 }
5916
5917 // Keep the conditions below in sync with the conditions in ReadFromCache.
5918
5919 rv = NS_OK;
5920
5921 if (WillRedirect(*mCachedResponseHead)) {
5922 // Do not even try to read the entity for a redirect because we do not
5923 // return an entity to the application when we process redirects.
5924 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
)
;
5925 return NS_OK;
5926 }
5927
5928 if ((mLoadFlags & nsICachingChannel::LOAD_ONLY_IF_MODIFIED) &&
5929 !LoadCachedContentIsPartial()) {
5930 // For LOAD_ONLY_IF_MODIFIED, we usually don't have to deal with the
5931 // cached entity.
5932 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)
5933 ("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)
5934 "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)
;
5935 return NS_OK;
5936 }
5937
5938 // Open an input stream for the entity, so that the call to OpenInputStream
5939 // happens off the main thread.
5940 nsCOMPtr<nsIInputStream> stream;
5941
5942 // If an alternate representation was requested, try to open the alt
5943 // input stream.
5944 // If the entry has a "is-from-child" metadata, then only open the altdata
5945 // stream if the consumer is also from child.
5946 bool altDataFromChild = false;
5947 {
5948 nsCString value;
5949 rv = cacheEntry->GetMetaDataElement("alt-data-from-child",
5950 getter_Copies(value));
5951 altDataFromChild = !value.IsEmpty();
5952 }
5953
5954 nsAutoCString altDataType;
5955 (void)cacheEntry->GetAltDataType(altDataType);
5956
5957 nsAutoCString contentType;
5958 mCachedResponseHead->ContentType(contentType);
5959
5960 // Alt-data written by a content process (bytecode cache) may only be
5961 // consumed by a load whose principal matches the one that produced it.
5962 if (altDataFromChild && !altDataType.IsEmpty()) {
5963 nsAutoCString storedOrigin;
5964 cacheEntry->GetMetaDataElement("alt-data-principal",
5965 getter_Copies(storedOrigin));
5966 nsAutoCString currentOrigin;
5967 GetAltDataBindingOrigin(currentOrigin);
5968 if (storedOrigin.IsEmpty() || currentOrigin.IsEmpty() ||
5969 !storedOrigin.Equals(currentOrigin)) {
5970 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal mismatch "
"[channel=%p, stored='%s', current='%s']", this, storedOrigin
.get(), currentOrigin.get()); } } while (0)
5971 ("Rejecting child-written alt-data due to principal mismatch "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal mismatch "
"[channel=%p, stored='%s', current='%s']", this, storedOrigin
.get(), currentOrigin.get()); } } while (0)
5972 "[channel=%p, stored='%s', current='%s']",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal mismatch "
"[channel=%p, stored='%s', current='%s']", this, storedOrigin
.get(), currentOrigin.get()); } } while (0)
5973 this, storedOrigin.get(), currentOrigin.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal mismatch "
"[channel=%p, stored='%s', current='%s']", this, storedOrigin
.get(), currentOrigin.get()); } } while (0)
;
5974 altDataType.Truncate();
5975 }
5976 }
5977
5978 bool foundAltData = false;
5979 bool deliverAltData = true;
5980 if (!LoadDisableAltDataCache() && !altDataType.IsEmpty() &&
5981 !mPreferredCachedAltDataTypes.IsEmpty() &&
5982 altDataFromChild == LoadAltDataForChild()) {
5983 for (auto& pref : mPreferredCachedAltDataTypes) {
5984 if (pref.type() == altDataType &&
5985 (pref.contentType().IsEmpty() || pref.contentType() == contentType)) {
5986 foundAltData = true;
5987 deliverAltData =
5988 pref.deliverAltData() ==
5989 nsICacheInfoChannel::PreferredAlternativeDataDeliveryType::ASYNC;
5990 break;
5991 }
5992 }
5993 }
5994
5995 nsCOMPtr<nsIInputStream> altData;
5996 int64_t altDataSize = -1;
5997 if (foundAltData) {
5998 rv = cacheEntry->OpenAlternativeInputStream(altDataType,
5999 getter_AddRefs(altData));
6000 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6001 // We have succeeded.
6002 mAvailableCachedAltDataType = altDataType;
6003 StoreDeliveringAltData(deliverAltData);
6004
6005 // Set the correct data size on the channel.
6006 (void)cacheEntry->GetAltDataSize(&altDataSize);
6007 mAltDataLength = altDataSize;
6008
6009 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)
6010 ", 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)
6011 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)
;
6012
6013 if (deliverAltData) {
6014 stream = altData;
6015 }
6016 }
6017 }
6018
6019 if (!stream) {
6020 rv = cacheEntry->OpenInputStream(0, getter_AddRefs(stream));
6021 }
6022
6023 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
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
, "Failed to open cache input stream [channel=%p, " "mCacheEntry=%p]"
, this, cacheEntry); } } while (0)
6025 ("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)
6026 "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)
6027 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)
;
6028 return rv;
6029 }
6030
6031 if (startBuffering) {
6032 bool nonBlocking;
6033 rv = stream->IsNonBlocking(&nonBlocking);
6034 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && nonBlocking) startBuffering = false;
6035 }
6036
6037 if (!startBuffering) {
6038 // Bypass wrapping the input stream for the new cache back-end since
6039 // nsIStreamTransportService expects a blocking stream. Preloading of
6040 // the data must be done on the level of the cache backend, internally.
6041 //
6042 // We do not connect the stream to the stream transport service if we
6043 // have to validate the entry with the server. If we did, we would get
6044 // into a race condition between the stream transport service reading
6045 // the existing contents and the opening of the cache entry's output
6046 // stream to write the new contents in the case where we get a non-304
6047 // response.
6048 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)
6049 ("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)
6050 "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)
6051 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)
;
6052 mCacheInputStream.takeOver(stream);
6053 return rv;
6054 }
6055
6056 // Have the stream transport service start reading the entity on one of its
6057 // background threads.
6058
6059 nsCOMPtr<nsITransport> transport;
6060 nsCOMPtr<nsIInputStream> wrapper;
6061
6062 nsCOMPtr<nsIStreamTransportService> sts(
6063 components::StreamTransport::Service());
6064 rv = sts ? NS_OK : NS_ERROR_NOT_AVAILABLE;
6065 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6066 rv = sts->CreateInputTransport(stream, true, getter_AddRefs(transport));
6067 }
6068 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6069 rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(wrapper));
6070 }
6071 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6072 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)
6073 ("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)
6074 "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)
6075 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)
;
6076 } else {
6077 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)
6078 ("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)
6079 "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)
6080 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)
;
6081
6082 stream->Close();
6083 return rv;
6084 }
6085
6086 mCacheInputStream.takeOver(wrapper);
6087
6088 return NS_OK;
6089}
6090
6091// Actually process the cached response that we started to handle in CheckCache
6092// and/or StartBufferingCachedEntity.
6093nsresult nsHttpChannel::ReadFromCache(void) {
6094 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"
, 6094); return NS_ERROR_FAILURE; } } while (false)
;
6095 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"
, 6095); return NS_ERROR_FAILURE; } } while (false)
;
6096 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"
, 6096); return NS_OK; } } while (false)
; // already opened
6097
6098 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)
6099 ("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)
6100 "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)
6101 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)
;
6102
6103 if (mCachedResponseHead) mResponseHead = std::move(mCachedResponseHead);
6104
6105 UpdateInhibitPersistentCachingFlag();
6106
6107 // if we don't already have security info, try to get it from the cache
6108 // entry. there are two cases to consider here: 1) we are just reading
6109 // from the cache, or 2) this may be due to a 304 not modified response,
6110 // in which case we could have security info from a socket transport.
6111 if (!mSecurityInfo) mSecurityInfo = mCachedSecurityInfo;
6112
6113 nsresult rv;
6114
6115 // Keep the conditions below in sync with the conditions in
6116 // StartBufferingCachedEntity.
6117
6118 if (WillRedirect(*mResponseHead)) {
6119 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
6120 // to avoid event dispatching latency.
6121 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", 6121
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6121); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6122 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)
;
6123 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
6124 }
6125
6126 if ((mLoadFlags & LOAD_ONLY_IF_MODIFIED) && !LoadCachedContentIsPartial()) {
6127 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)
6128 ("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)
6129 "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)
;
6130 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", 6130
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6130); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6131 // TODO: Bug 759040 - We should call HandleAsyncNotModified directly
6132 // here, to avoid event dispatching latency.
6133 return AsyncCall(&nsHttpChannel::HandleAsyncNotModified);
6134 }
6135
6136 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", 6136
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6136); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6137 if (!mCacheInputStream) {
6138 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"
, 6140); MOZ_PretendNoReturn(); } while (0)
6139 "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"
, 6140); MOZ_PretendNoReturn(); } while (0)
6140 "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"
, 6140); MOZ_PretendNoReturn(); } while (0)
;
6141 return NS_ERROR_UNEXPECTED;
6142 }
6143
6144 nsCOMPtr<nsIInputStream> inputStream = mCacheInputStream.forget();
6145
6146 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), inputStream, 0, 0,
6147 true);
6148 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6149 inputStream->Close();
6150 return rv;
6151 }
6152
6153 rv = mCachePump->AsyncRead(this);
6154 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6155
6156 uint32_t suspendCount = mSuspendCount;
6157 if (LoadAsyncResumePending()) {
6158 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)
6159 (" 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)
6160 ", 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)
6161 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)
;
6162 ++suspendCount;
6163 }
6164 while (suspendCount--) {
6165 mCachePump->Suspend();
6166 }
6167
6168 return NS_OK;
6169}
6170
6171void nsHttpChannel::CloseCacheEntry(bool doomOnFailure) {
6172 CancelCacheWaitTimer();
6173 mCacheInputStream.CloseAndRelease();
6174
6175 if (!mCacheEntry) return;
6176
6177 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)
6178 " 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)
6179 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)
6180 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)
;
6181
6182 // If we have begun to create or replace a cache entry, and that cache
6183 // entry is not complete and not resumable, then it needs to be doomed.
6184 // Otherwise, CheckCache will make the mistake of thinking that the
6185 // partial cache entry is complete.
6186
6187 bool doom = false;
6188 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref) {
6189 // A response blocked by ORB is fully written to the cache before the block
6190 // decision is made, so it must be doomed here; otherwise it lingers as a
6191 // complete entry that a same-partition request (e.g. a navigation reusing a
6192 // prefetch) could consume.
6193 doom = true;
6194 } else if (LoadInitedCacheEntry()) {
6195 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"
, 6195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "oops" ")"); do { MOZ_CrashSequence(__null, 6195); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6196 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) && doomOnFailure && LoadCacheEntryIsWriteOnly() &&
6197 (!mResponseHead || !mResponseHead->IsResumable())) {
6198 doom = true;
6199 }
6200 } else if (LoadCacheEntryIsWriteOnly()) {
6201 doom = true;
6202 }
6203
6204 if (doom) {
6205 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)
;
6206 mCacheEntry->AsyncDoom(nullptr);
6207 } else {
6208 // Store updated security info, makes cached EV status race less likely
6209 // (see bug 1040086). On a plain cache hit ReadFromCache() adopted the info
6210 // this very entry handed us in OpenCacheInputStream(), so storing it back
6211 // would only re-serialize the certificate chain and rewrite the entry file.
6212 if (mSecurityInfo && mSecurityInfo != mCachedSecurityInfo) {
6213 mCacheEntry->SetSecurityInfo(mSecurityInfo);
6214 }
6215
6216 // For prefetch requests without cache headers, force the cache entry
6217 // to remain valid so that subsequent navigations reuse the prefetched
6218 // response instead of re-fetching. See bug 1527334.
6219 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && mResponseHead) {
6220 if (StringBeginsWith(GetSecPurpose(), "prefetch"_ns) &&
6221 !mResponseHead->MustValidate()) {
6222 nsAutoCString expires;
6223 (void)mResponseHead->GetHeader(nsHttp::Expires, expires);
6224 nsAutoCString cacheControlHeader;
6225 (void)mResponseHead->GetHeader(nsHttp::Cache_Control,
6226 cacheControlHeader);
6227 CacheControlParser cacheControl(cacheControlHeader);
6228 uint32_t maxAge;
6229 if (!cacheControl.MaxAge(&maxAge) && expires.IsEmpty()) {
6230 uint32_t forceValidFor =
6231 StaticPrefs::network_prefetch_next_force_valid_for();
6232 if (forceValidFor > 0) {
6233 mCacheEntry->ForceValidFor(forceValidFor);
6234 }
6235 }
6236 }
6237 }
6238
6239 // ORB's JavaScript validation finishes asynchronously, after this point,
6240 // so the response may yet be blocked. Keep a reference to the committed
6241 // entry so CancelInternal() can doom it if that happens.
6242 if (mORB && mORB->IsSniffing()) {
6243 mORBValidationCacheEntry = mCacheEntry;
6244 }
6245 }
6246
6247 mCachedResponseHead = nullptr;
6248
6249 mCachePump = nullptr;
6250 // This releases the entry for other consumers to use.
6251 // We call Dismiss() in case someone still keeps a reference
6252 // to this entry handle.
6253 mCacheEntry->Dismiss();
6254 mCacheEntry = nullptr;
6255 StoreCacheEntryIsWriteOnly(false);
6256 StoreInitedCacheEntry(false);
6257}
6258
6259void nsHttpChannel::OnOpaqueResponseAllowed() {
6260 // mORBValidationCacheEntry is only ever touched on the main thread; this
6261 // relies on ORB delivering its validation verdict there.
6262 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", 6262
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 6262); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6263 // ORB allowed the response, so the entry we kept in case it had to be doomed
6264 // (see CloseCacheEntry) can stay in the cache; drop our reference to it.
6265 mORBValidationCacheEntry = nullptr;
6266}
6267
6268// Initialize the cache entry for writing.
6269// - finalize storage policy
6270// - store security info
6271// - update expiration time
6272// - store headers and other meta data
6273nsresult nsHttpChannel::InitCacheEntry() {
6274 nsresult rv;
6275
6276 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"
, 6276); return NS_ERROR_UNEXPECTED; } } while (false)
;
6277 // if only reading, nothing to be done here.
6278 if (LoadCacheEntryIsReadOnly()) return NS_OK;
6279
6280 // Don't cache the response again if already cached...
6281 if (CachedContentIsValid()) return NS_OK;
6282
6283 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)
6284 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)
;
6285
6286 // Normally already handled before the response was applied to the entry, but
6287 // recreating an alias entry would doom and rewrite another URL's entry, so
6288 // never reach Recreate() below while the flag is still set.
6289 rv = MaybeReplaceNoVarySearchAliasEntry();
6290 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return NS_OK;
6291
6292 bool recreate = !LoadCacheEntryIsWriteOnly();
6293 bool dontPersist = mLoadFlags & INHIBIT_PERSISTENT_CACHING;
6294
6295 if (!recreate && dontPersist) {
6296 // If the current entry is persistent but we inhibit peristence
6297 // then force recreation of the entry as memory/only.
6298 rv = mCacheEntry->GetPersistent(&recreate);
6299 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6300 }
6301
6302 if (recreate) {
6303 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)
6304 (" 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)
6305 "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)
;
6306 // clean the altData cache and reset this to avoid wrong content length
6307 mAvailableCachedAltDataType.Truncate();
6308 StoreDeliveringAltData(false);
6309
6310 nsCOMPtr<nsICacheEntry> currentEntry;
6311 currentEntry.swap(mCacheEntry);
6312 rv = currentEntry->Recreate(dontPersist, getter_AddRefs(mCacheEntry));
6313 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6314 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)
;
6315 return NS_OK;
6316 }
6317
6318 StoreCacheEntryIsWriteOnly(true);
6319
6320 // Since we recreated, the new entry doesn't have expiration set yet.
6321 // UpdateExpirationTime was called before ParseDictionary on the old entry,
6322 // but we need to set it on this new entry too.
6323 rv = UpdateExpirationTime();
6324 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6325 }
6326
6327 // mark this weakly framed until a response body is seen
6328 mCacheEntry->SetMetaDataElement("strongly-framed", "0");
6329
6330 rv = AddCacheEntryHeaders(mCacheEntry, false);
6331 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6332
6333 StoreInitedCacheEntry(true);
6334
6335 // Don't perform the check when writing (doesn't make sense)
6336 StoreConcurrentCacheAccess(0);
6337
6338 return NS_OK;
6339}
6340
6341void nsHttpChannel::UpdateInhibitPersistentCachingFlag() {
6342 // The no-store directive within the 'Cache-Control:' header indicates
6343 // that we must not store the response in a persistent cache.
6344 if (mResponseHead->NoStore()) {
6345 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6346 return;
6347 }
6348
6349 if (!StaticPrefs::network_cache_persist_permanent_redirects_http() &&
6350 mURI->SchemeIs("http") &&
6351 nsHttp::IsPermanentRedirect(mResponseHead->Status())) {
6352 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6353 return;
6354 }
6355
6356 // Only cache SSL content on disk if the pref is set
6357 if (!gHttpHandler->IsPersistentHttpsCachingEnabled() &&
6358 mURI->SchemeIs("https")) {
6359 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6360 }
6361}
6362
6363nsresult DoAddCacheEntryHeaders(nsHttpChannel* self, nsICacheEntry* entry,
6364 nsHttpRequestHead* requestHead,
6365 nsHttpResponseHead* responseHead,
6366 nsITransportSecurityInfo* securityInfo,
6367 bool aModified) {
6368 nsresult rv;
6369
6370 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)
;
6371 // Store secure data in memory only
6372 if (securityInfo) {
6373 entry->SetSecurityInfo(securityInfo);
6374 }
6375
6376 // Note: if aModified == false, then we're processing a 304 Not Modified,
6377 // and we *shouldn't* have any change to the Dictionary (and won't be
6378 // replacing the DictionaryEntry, though if the Match/Match-dest/Id/Type
6379 // changed, we may need to rewrite it. XXX?
6380
6381 // Store the HTTP request method with the cache entry so we can distinguish
6382 // for example GET and HEAD responses.
6383 nsAutoCString method;
6384 requestHead->Method(method);
6385 rv = entry->SetMetaDataElement("request-method", method.get());
6386 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6387
6388 // Store the HTTP authorization scheme used if any...
6389 rv = StoreAuthorizationMetaData(entry, requestHead);
6390 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6391
6392 rv = self->UpdateCacheEntryHeaders(entry, nullptr);
6393 return rv;
6394}
6395
6396nsresult nsHttpChannel::AddCacheEntryHeaders(nsICacheEntry* entry,
6397 bool aModified) {
6398 return DoAddCacheEntryHeaders(this, entry, &mRequestHead, mResponseHead.get(),
6399 mSecurityInfo, aModified);
6400}
6401
6402nsresult nsHttpChannel::UpdateCacheEntryHeaders(nsICacheEntry* entry,
6403 const nsHttpAtom* aAtom) {
6404 nsresult rv = NS_OK;
6405
6406 // Iterate over the headers listed in the Vary response header, and
6407 // store the value of the corresponding request header so we can verify
6408 // that it has not varied when we try to re-use the cached response at
6409 // a later time. Take care to store "Cookie" headers only as hashes
6410 // due to security considerations and the fact that they can be pretty
6411 // large (bug 468426). We take care of "Vary: cookie" in ResponseWouldVary.
6412 //
6413 // NOTE: if "Vary: accept, cookie", then we will store the "accept" header
6414 // in the cache. we could try to avoid needlessly storing the "accept"
6415 // header in this case, but it doesn't seem worth the extra code to perform
6416 // the check.
6417 {
6418 nsAutoCString buf, metaKey;
6419 (void)mResponseHead->GetHeader(nsHttp::Vary, buf);
6420
6421 constexpr auto prefix = "request-"_ns;
6422
6423 for (const nsACString& token :
6424 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
6425 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)
6426 ("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)
6427 "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)
6428 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)
;
6429 if (!token.EqualsLiteral("*")) {
6430 nsHttpAtom atom = nsHttp::ResolveAtom(token);
6431 if (!aAtom || atom == *aAtom) {
6432 nsAutoCString val;
6433 nsAutoCString hash;
6434 if (NS_SUCCEEDED(mRequestHead.GetHeader(atom, val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(atom, val))), 1)))
) {
6435 // If cookie-header, store a hash of the value
6436 if (atom == nsHttp::Cookie) {
6437 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "cookie-value %s"
, this, val.get()); } } while (0)
6438 ("nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "cookie-value %s"
, this, val.get()); } } while (0)
6439 "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)
6440 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)
;
6441 rv = Hash(val.get(), hash);
6442 // If hash failed, store a string not very likely
6443 // to be the result of subsequent hashes
6444 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6445 val = "<hash failed>"_ns;
6446 } else {
6447 val = std::move(hash);
6448 }
6449
6450 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)
;
6451 }
6452
6453 // build cache meta data key and set meta data element...
6454 metaKey = prefix + token;
6455 entry->SetMetaDataElement(metaKey.get(), val.get());
6456 } else {
6457 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)
6458 ("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)
6459 "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)
6460 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)
;
6461 metaKey = prefix + token;
6462 entry->SetMetaDataElement(metaKey.get(), nullptr);
6463 }
6464 }
6465 }
6466 }
6467 }
6468 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6469 return rv;
6470 }
6471 // Store the received HTTP head with the cache entry as an element of
6472 // the meta data.
6473 nsAutoCString head;
6474 mResponseHead->Flatten(head, true);
6475 rv = entry->SetMetaDataElement("response-head", head.get());
6476 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6477 head.Truncate();
6478 mResponseHead->FlattenNetworkOriginalHeaders(head);
6479 rv = entry->SetMetaDataElement("original-response-headers", head.get());
6480 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6481
6482 // Store No-Vary-Search header in cache metadata and notify the secondary
6483 // index so variant URLs can match this entry on future cache lookups.
6484 nsAutoCString noVarySearch;
6485 if (StaticPrefs::network_cache_no_vary_search() &&
6486 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::No_Vary_Search, noVarySearch))), 1)))
6487 mResponseHead->GetHeader(nsHttp::No_Vary_Search, noVarySearch))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::No_Vary_Search, noVarySearch))), 1)))
&&
6488 !noVarySearch.IsEmpty()) {
6489 glean::network::no_vary_search_header_received.Add(1);
6490 bool parseError = false;
6491 auto data = ParseNoVarySearchHeader(noVarySearch, &parseError);
6492 glean::network::no_vary_search_rule_type
6493 .Get(NoVarySearchRuleLabel(data.paramsRule))
6494 .Add(1);
6495 if (parseError) {
6496 glean::network::no_vary_search_parse_error.Add(1);
6497 }
6498
6499 rv = entry->SetMetaDataElement("no-vary-search", noVarySearch.get());
6500 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6501 return rv;
6502 }
6503
6504 if (mCacheEntryURI) {
6505 if (auto* svc = CacheStorageService::Self()) {
6506 svc->NoteNoVarySearchEntry(entry, mCacheEntryURI);
6507 }
6508 }
6509 }
6510
6511 // Indicate we have successfully finished setting metadata on the cache
6512 // entry.
6513 return entry->MetaDataReady();
6514}
6515
6516bool nsHttpChannel::ParseDictionary(nsICacheEntry* aEntry,
6517 nsHttpResponseHead* aResponseHead,
6518 bool aModified) {
6519 nsAutoCString val;
6520 if (NS_SUCCEEDED(aResponseHead->GetHeader(nsHttp::Use_As_Dictionary, val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Use_As_Dictionary, val))), 1)))
) {
6521 nsAutoCStringN<128> matchVal;
6522 nsAutoCStringN<64> matchIdVal;
6523 nsTArray<nsCString> matchDestItems;
6524 nsAutoCString typeVal;
6525
6526 if (!NS_ParseUseAsDictionary(val, matchVal, matchIdVal, matchDestItems,
6527 typeVal)) {
6528 return false;
6529 }
6530
6531 nsCString key;
6532 nsresult rv;
6533 if (NS_FAILED(rv = aEntry->GetKey(key))((bool)(__builtin_expect(!!(NS_FAILED_impl(rv = aEntry->GetKey
(key))), 0)))
) {
6534 return false;
6535 }
6536
6537 // Verify if the matchVal has regexp groups. If so, reject it
6538 UrlPatternGlue pattern;
6539 UrlPatternOptions options{};
6540 if (!urlpattern_parse_pattern_from_string(&matchVal, &mSpec, options,
6541 &pattern)) {
6542 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)
6543 ("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)
;
6544 return false;
6545 }
6546
6547 auto freePattern = MakeScopeExit([&] { urlpattern_pattern_free(pattern); });
6548 if (urlpattern_get_has_regexp_groups(pattern)) {
6549 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)
;
6550 return false;
6551 }
6552
6553 nsCString hash;
6554 // Available now for use
6555 RefPtr<DictionaryCache> dicts(DictionaryCache::GetInstance());
6556 if (!dicts) {
6557 // Shutdown has occurred, cannot add dictionary
6558 return false;
6559 }
6560 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)
6561 ("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)
6562 "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)
6563 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)
6564 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)
6565 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)
;
6566
6567 uint32_t expTime = 0;
6568 (void)GetCacheTokenExpirationTime(&expTime);
6569
6570 RefPtr<LoadContextInfo> lci = GetLoadContextInfo(this);
6571 dicts->AddEntry(mURI, key, matchVal, matchDestItems, matchIdVal, Some(hash),
6572 aModified, expTime, lci, getter_AddRefs(mDictSaving));
6573 // If this was 304 Not Modified, then we don't need the dictionary data
6574 // (though we may update the dictionary entry if the match/id/etc changed).
6575 // If this is 304, mDictSaving will be cleared by AddEntry.
6576 if (mDictSaving) {
6577 if (mDictSaving->ShouldSuspendUntilCacheRead()) {
6578 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)
;
6579 Suspend();
6580 mDictSaving->CallbackOnCacheRead([self = RefPtr(this)](nsresult) {
6581 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)
;
6582 self->Resume();
6583 });
6584 }
6585 }
6586 return true;
6587 }
6588 return true; // succeeded, no use-as-dictionary
6589}
6590
6591inline void GetAuthType(const char* challenge, nsCString& authType) {
6592 const char* p;
6593
6594 // get the challenge type
6595 if ((p = strchr(challenge, ' ')) != nullptr) {
6596 authType.Assign(challenge, p - challenge);
6597 } else {
6598 authType.Assign(challenge);
6599 }
6600}
6601
6602nsresult StoreAuthorizationMetaData(nsICacheEntry* entry,
6603 nsHttpRequestHead* requestHead) {
6604 // Not applicable to proxy authorization...
6605 nsAutoCString val;
6606 if (NS_FAILED(requestHead->GetHeader(nsHttp::Authorization, val))((bool)(__builtin_expect(!!(NS_FAILED_impl(requestHead->GetHeader
(nsHttp::Authorization, val))), 0)))
) {
6607 return NS_OK;
6608 }
6609
6610 // eg. [Basic realm="wally world"]
6611 nsAutoCString buf;
6612 GetAuthType(val.get(), buf);
6613 return entry->SetMetaDataElement("auth", buf.get());
6614}
6615
6616// Finalize the cache entry
6617// - may need to rewrite response headers if any headers changed
6618// - may need to recalculate the expiration time if any headers changed
6619// - called only for freshly written cache entries
6620nsresult nsHttpChannel::FinalizeCacheEntry() {
6621 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)
;
6622
6623 // Don't update this meta-data on 304
6624 if (LoadStronglyFramed() && !CachedContentIsValid() && mCacheEntry) {
6625 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)
6626 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
6627 mCacheEntry->SetMetaDataElement("strongly-framed", "1");
6628 }
6629
6630 if (mResponseHead && LoadResponseHeadersModified()) {
6631 // Set the expiration time for this cache entry
6632 nsresult rv = UpdateExpirationTime();
6633 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6634 }
6635 return NS_OK;
6636}
6637
6638nsresult nsHttpChannel::InstallCacheListener(int64_t offset) {
6639 return DoInstallCacheListener(false, offset);
6640}
6641
6642// Open an output stream to the cache entry and insert a listener tee into
6643// the chain of response listeners, so the data will go the cache and the
6644// normal listener chain, which often will eventually include a
6645// decompressor. If the Content-Encoding is dcb or dcz, we'll include a
6646// decompressor *before* the tee, so the cache will see decompressed data
6647// (we can't decompress dcb/dcz when reading from the cache). Also, if an
6648// entry is being used as a dictionary (Use-As-Dictionary), we want the data
6649// to in the cache to be decompressed, so we should install a decompressor
6650// before the tee as well.
6651nsresult nsHttpChannel::DoInstallCacheListener(bool aSaveDecompressed,
6652 int64_t offset) {
6653 nsresult rv;
6654
6655 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)
;
6656
6657 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"
, 6657); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 6657); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6658 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", 6658
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial()"
")"); do { MOZ_CrashSequence(__null, 6658); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6659 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"
, 6659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mListener" ")"
); do { MOZ_CrashSequence(__null, 6659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6660
6661 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)
;
6662
6663 // We must close the input stream first because cache entries do not
6664 // correctly handle having an output stream and input streams open at
6665 // the same time.
6666 mCacheInputStream.CloseAndRelease();
6667
6668 int64_t predictedSize = mResponseHead->TotalEntitySize();
6669 if (predictedSize != -1) {
6670 predictedSize -= offset;
6671 }
6672
6673 nsCOMPtr<nsIOutputStream> out;
6674 rv =
6675 mCacheEntry->OpenOutputStream(offset, predictedSize, getter_AddRefs(out));
6676 if (rv == NS_ERROR_NOT_AVAILABLE) {
6677 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)
;
6678 // Entry is already doomed.
6679 // This may happen when expiration time is set to past and the entry
6680 // has been removed by the background eviction logic.
6681 return NS_OK;
6682 }
6683 if (rv == NS_ERROR_FILE_TOO_BIG) {
6684 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)
6685 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
6686 mCacheEntry->AsyncDoom(nullptr);
6687 return NS_OK;
6688 }
6689 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6690
6691 if (LoadCacheOnlyMetadata()) {
6692 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
)
;
6693 // We must open and then close the output stream of the cache entry.
6694 // This way we indicate the content has been written (despite with zero
6695 // length) and the entry is now in the ready state with "having data".
6696
6697 out->Close();
6698 return NS_OK;
6699 }
6700
6701 // XXX disk cache does not support overlapped i/o yet
6702#if 0
6703 // Mark entry valid inorder to allow simultaneous reading...
6704 rv = mCacheEntry->MarkValid();
6705 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6706#endif
6707
6708 nsCOMPtr<nsIStreamListenerTee> tee =
6709 do_CreateInstance(kStreamListenerTeeCID, &rv);
6710 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6711
6712 rv = tee->Init(mListener, out, nullptr);
6713 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)
6714 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)
;
6715 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6716 mListener = tee;
6717
6718 mWritingToCache = true;
6719 // If this is Use-As-Dictionary we need to be able to read it quickly for
6720 // dictionary use, OR if it's encoded in dcb or dcz (using a dictionary),
6721 // we must decompress it before storing since we won't have the dictionary
6722 // when we go to read it out later.
6723 // In this case, we hook an nsHTTPCompressConv instance in before the tee
6724 // since we don't want to have to decompress it here and again in the content
6725 // process (if it's not dcb/dcz); if it is dcb/dcz we must decompress it
6726 // before the content process gets to see it
6727 // XXX We could recompress this with e.g. gzip to save space and improve
6728 // hitrate, at the cost of some CPU.
6729
6730 // Note: this doesn't handle cases like "dcb, gzip" or (worse?) "gzip, dcb".
6731 // We could in theory handle them.
6732 if (aSaveDecompressed) {
6733 nsCOMPtr<nsIStreamListener> listener;
6734 // otherwise we won't convert in the parent process
6735 SetApplyConversion(true);
6736 rv = DoApplyContentConversionsInternal(mListener, getter_AddRefs(listener),
6737 true, nullptr);
6738 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6739 return rv;
6740 }
6741 // Remove Available-Dictionary from Vary header if present. This
6742 // avoids us refusing to match on a future load, for example if this
6743 // dictionary was decoded from an earlier version using a dictionary
6744 // (i.e. the update jquery to new version using the old version as a
6745 // dictionary; no future load will use that old version).
6746
6747 // XXX It would be slightly more efficient to remove all at once
6748 // instead of sequentially by passing an array of strings
6749 RemoveFromVary(mResponseHead.get(), "available-dictionary"_ns);
6750 RemoveFromVary(mResponseHead.get(), "accept-encoding"_ns);
6751
6752 if (listener) {
6753 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)
6754 ("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)
;
6755 mListener = listener;
6756 mCompressListener = std::move(listener);
6757 StoreHasAppliedConversion(true);
6758
6759 } else {
6760 nsAutoCString contentEncoding;
6761 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
6762 if (contentEncoding.IsEmpty()) {
6763 // No Content-Encoding — data is already raw. Normal for dictionary
6764 // responses served without transfer encoding.
6765 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)
6766 ("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)
;
6767 } else if (mIsDictionaryCompressed) {
6768 // dcb/dcz can only be decompressed in the parent process with
6769 // the dictionary. If we can't install the decompressor, this is
6770 // fatal — the content process can't decode it.
6771 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)
6772 ("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)
6773 "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)
6774 "[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)
6775 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)
6776 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)
;
6777 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
6778 return NS_ERROR_INVALID_CONTENT_ENCODING;
6779 } else if (mDictSaving) {
6780 // Saving a dictionary but can't install a decompressor — we'd store
6781 // compressed data with a hash computed over compressed bytes. Cancel
6782 // the dictionary save but leave Content-Encoding for downstream
6783 // decompression.
6784 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)
6785 ("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)
6786 "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)
6787 "[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)
6788 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)
6789 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)
;
6790 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"
, 6790); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Can't save dictionary uncompressed" ")"); do { MOZ_CrashSequence
(__null, 6790); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6791 mCacheEntry->SetDictionary(nullptr);
6792 DictionaryCache::RemoveDictionary(nsCString(mDictSaving->GetURI()),
6793 mDictSaving->GetLoadContextInfo());
6794 mDictSaving = nullptr;
6795 }
6796 }
6797 // We may have modified Content-Encoding; make sure cache metadata
6798 // reflects that. Pass nullptr so we pick up the Vary updates above
6799 rv = UpdateCacheEntryHeaders(mCacheEntry, nullptr);
6800 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6801 mCacheEntry->AsyncDoom(nullptr);
6802 return rv;
6803 }
6804 }
6805
6806#ifdef DEBUG1
6807 // Verify that Content-Encoding was properly cleared
6808 nsAutoCString verifyEncoding;
6809 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, verifyEncoding);
6810 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"
, 6811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
") (" "Content-Encoding should have been cleared for dcb/dcz"
")"); do { MOZ_CrashSequence(__null, 6811); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6811 "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"
, 6811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
") (" "Content-Encoding should have been cleared for dcb/dcz"
")"); do { MOZ_CrashSequence(__null, 6811); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6812 if (aSaveDecompressed) {
6813 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"
, 6815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6815); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6814 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"
, 6815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6815); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6815 "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"
, 6815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6815); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6816 }
6817#endif
6818 return NS_OK;
6819}
6820
6821//-----------------------------------------------------------------------------
6822// nsHttpChannel <redirect>
6823//-----------------------------------------------------------------------------
6824
6825nsresult nsHttpChannel::SetupReplacementChannel(nsIURI* newURI,
6826 nsIChannel* newChannel,
6827 bool preserveMethod,
6828 uint32_t redirectFlags) {
6829 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)
6830 ("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)
6831 "[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)
6832 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)
;
6833
6834 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
6835 mEndMarkerAdded = true;
6836
6837 nsAutoCString requestMethod;
6838 GetRequestMethod(requestMethod);
6839
6840 int32_t priority = PRIORITY_NORMAL;
6841 GetPriority(&priority);
6842
6843 TimingStruct timings;
6844 if (mTransaction) {
6845 timings = mTransaction->Timings();
6846 }
6847
6848 uint64_t size = 0;
6849 GetEncodedBodySize(&size);
6850
6851 nsAutoCString contentType;
6852 mozilla::Maybe<mozilla::net::HttpVersion> httpVersion = Nothing();
6853 mozilla::Maybe<uint32_t> responseStatus = Nothing();
6854 if (mResponseHead) {
6855 mResponseHead->ContentType(contentType);
6856 httpVersion = Some(mResponseHead->Version());
6857 responseStatus = Some(mResponseHead->Status());
6858 }
6859
6860 RefPtr<nsIIdentChannel> newIdentChannel = do_QueryObject(newChannel);
6861 uint64_t channelId = 0;
6862 if (newIdentChannel) {
6863 channelId = newIdentChannel->ChannelId();
6864 }
6865 profiler_add_network_marker(
6866 mURI, requestMethod, priority, mChannelId,
6867 NetworkLoadType::LOAD_REDIRECT, mLastStatusReported, TimeStamp::Now(),
6868 size, mCacheDisposition, mLoadInfo->GetInnerWindowID(),
6869 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
6870 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
6871 &timings, std::move(mSource), httpVersion, responseStatus,
6872 Some(nsDependentCString(contentType.get())), newURI, redirectFlags,
6873 channelId);
6874 }
6875
6876 nsresult rv = HttpBaseChannel::SetupReplacementChannel(
6877 newURI, newChannel, preserveMethod, redirectFlags);
6878 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6879
6880 nsAutoCString uriHost;
6881 mURI->GetAsciiHost(uriHost);
6882 // disable https-rr when encountering a downgrade from https to http.
6883 // If the host would have https-rr dns-entries, it would be misconfigured
6884 // due to giving us mixed signals:
6885 // 1. the signal to upgrade all http requests to https,
6886 // 2. but also downgrading to http on https via redirects.
6887 // Add to exclude list for that reason
6888 if (!gHttpHandler->IsHostExcludedForHTTPSRR(uriHost) &&
6889 nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
6890 mURI, newURI, mLoadInfo,
6891 {nsHTTPSOnlyUtils::UpgradeDowngradeEndlessLoopOptions::
6892 EnforceForHTTPSRR})) {
6893 // Add the host to a excluded list because:
6894 // 1. We don't need to do the same check again.
6895 // 2. Other subresources in the same host will be also excluded.
6896 gHttpHandler->ExcludeHTTPSRRHost(uriHost);
6897 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)
;
6898 }
6899
6900 rv = CheckRedirectLimit(newURI, redirectFlags);
6901 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"
, 6901); return rv; } } while (false)
;
6902
6903 // pass on the early hint observer to be able to process `103 Early Hints`
6904 // responses after cross origin redirects
6905 if (mEarlyHintObserver) {
6906 if (RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel)) {
6907 httpChannelImpl->SetEarlyHintObserver(mEarlyHintObserver);
6908 }
6909 mEarlyHintObserver = nullptr;
6910 }
6911
6912 // We don't support redirection for WebTransport for now.
6913 mWebTransportSessionEventListener = nullptr;
6914
6915 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
6916 if (!httpChannel) return NS_OK; // no other options to set
6917
6918 // convey the ApplyConversion flag (bug 91862)
6919 nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel);
6920 if (encodedChannel) encodedChannel->SetApplyConversion(LoadApplyConversion());
6921
6922 // transfer the resume information
6923 if (LoadResuming()) {
6924 nsCOMPtr<nsIResumableChannel> resumableChannel(
6925 do_QueryInterface(newChannel));
6926 if (!resumableChannel) {
6927 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Got asked to resume, but redirected to non-resumable channel!"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6928)
6928 "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"
, 6928)
;
6929 return NS_ERROR_NOT_RESUMABLE;
6930 }
6931 resumableChannel->ResumeAt(mStartPos, mEntityID);
6932 }
6933
6934 nsCOMPtr<nsIHttpChannelInternal> internalChannel =
6935 do_QueryInterface(newChannel, &rv);
6936 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6937 TimeStamp timestamp;
6938 rv = GetNavigationStartTimeStamp(&timestamp);
6939 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"
, 6939)
) {
6940 return rv;
6941 }
6942 if (timestamp) {
6943 (void)internalChannel->SetNavigationStartTimeStamp(timestamp);
6944 }
6945 }
6946
6947 return NS_OK;
6948}
6949
6950nsresult nsHttpChannel::AsyncProcessRedirection(uint32_t redirectType) {
6951 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)
6952 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)
;
6953
6954 nsresult rv = ProcessCrossOriginSecurityHeaders();
6955 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6956 mStatus = rv;
6957 HandleAsyncAbort();
6958 return rv;
6959 }
6960
6961 nsAutoCString location;
6962
6963 // if a location header was not given, then we can't perform the redirect,
6964 // so just carry on as though this were a normal response.
6965 if (NS_FAILED(mResponseHead->GetHeader(nsHttp::Location, location))((bool)(__builtin_expect(!!(NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Location, location))), 0)))
) {
6966 return NS_ERROR_FAILURE;
6967 }
6968
6969 // If we were told to not follow redirects automatically, then again
6970 // carry on as though this were a normal response.
6971 if (mLoadInfo->GetDontFollowRedirects()) {
6972 return NS_ERROR_FAILURE;
6973 }
6974
6975 // make sure non-ASCII characters in the location header are escaped.
6976 nsAutoCString locationBuf;
6977 if (NS_EscapeURL(location.get(), -1, esc_OnlyNonASCII | esc_Spaces,
6978 locationBuf)) {
6979 location = std::move(locationBuf);
6980 }
6981
6982 mRedirectType = redirectType;
6983
6984 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)
6985 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)
;
6986
6987 rv = CreateNewURI(location.get(), getter_AddRefs(mRedirectURI));
6988
6989 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6990 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)
;
6991 return NS_ERROR_CORRUPTED_CONTENT;
6992 }
6993
6994 if (!StaticPrefs::network_allow_redirect_to_data() &&
6995 !mLoadInfo->GetAllowInsecureRedirectToDataURI() &&
6996 mRedirectURI->SchemeIs("data")) {
6997 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)
;
6998 nsContentSecurityManager::ReportBlockedDataURI(mRedirectURI, mLoadInfo,
6999 true);
7000 return NS_ERROR_DOM_BAD_URI;
7001 }
7002
7003 // Perform the URL query string stripping for redirects. We will only strip
7004 // the query string if it is redirecting to a third-party URI in the top
7005 // level.
7006 if (StaticPrefs::privacy_query_stripping_redirect()) {
7007 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
7008 bool isThirdPartyRedirectURI = true;
7009 thirdPartyUtil->IsThirdPartyURI(mURI, mRedirectURI,
7010 &isThirdPartyRedirectURI);
7011 if (isThirdPartyRedirectURI && mLoadInfo->GetExternalContentPolicyType() ==
7012 ExtContentPolicy::TYPE_DOCUMENT) {
7013 glean::contentblocking::query_stripping_count
7014 .EnumGet(glean::contentblocking::QueryStrippingCountLabel::eRedirect)
7015 .Add();
7016
7017 nsCOMPtr<nsIPrincipal> prin;
7018 ContentBlockingAllowList::RecomputePrincipal(
7019 mRedirectURI, mLoadInfo->GetOriginAttributes(), getter_AddRefs(prin));
7020
7021 bool isRedirectURIInAllowList = false;
7022 if (prin) {
7023 ContentBlockingAllowList::Check(prin, mPrivateBrowsing,
7024 isRedirectURIInAllowList);
7025 }
7026
7027 if (!isRedirectURIInAllowList) {
7028 nsCOMPtr<nsIURI> strippedURI;
7029
7030 nsCOMPtr<nsIURLQueryStringStripper> queryStripper;
7031 queryStripper =
7032 mozilla::components::URLQueryStringStripper::Service(&rv);
7033 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"
, 7033); return rv; } } while (false)
;
7034
7035 uint32_t numStripped;
7036
7037 rv = queryStripper->Strip(mRedirectURI, mPrivateBrowsing,
7038 getter_AddRefs(strippedURI), &numStripped);
7039 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"
, 7039); return rv; } } while (false)
;
7040
7041 if (numStripped) {
7042 mUnstrippedRedirectURI = mRedirectURI;
7043 mRedirectURI = strippedURI;
7044
7045 // Record telemetry, but only if we stripped any query params.
7046 glean::contentblocking::query_stripping_count
7047 .EnumGet(glean::contentblocking::QueryStrippingCountLabel::
7048 eStripforredirect)
7049 .Add();
7050 glean::contentblocking::query_stripping_param_count
7051 .AccumulateSingleSample(numStripped);
7052 }
7053 }
7054 }
7055 }
7056
7057 // if we have a Set-Login header, we should try to handle it here
7058 nsAutoCString setLogin;
7059 if (NS_SUCCEEDED(mResponseHead->GetHeader(nsHttp::Set_Login, setLogin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Set_Login, setLogin))), 1)))
) {
7060 bool isDocument = mLoadInfo->GetExternalContentPolicyType() ==
7061 ExtContentPolicy::TYPE_DOCUMENT;
7062 if (isDocument) {
7063 auto ssm = nsContentUtils::GetSecurityManager();
7064 if (ssm) {
7065 nsCOMPtr<nsIPrincipal> documentPrincipal;
7066 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
7067 this, getter_AddRefs(documentPrincipal));
7068 dom::NavigatorLogin::SetLoginStatus(documentPrincipal, setLogin);
7069 }
7070 } else {
7071 bool inThirdPartyContext = mLoadInfo->GetIsInThirdPartyContext();
7072 nsIPrincipal* loadingPrincipal = mLoadInfo->GetLoadingPrincipal();
7073 if (loadingPrincipal) {
7074 bool isSameOriginToLoadingPrincipal =
7075 loadingPrincipal->IsSameOrigin(mURI);
7076 if (!inThirdPartyContext && isSameOriginToLoadingPrincipal) {
7077 dom::NavigatorLogin::SetLoginStatus(loadingPrincipal, setLogin);
7078 }
7079 }
7080 }
7081 }
7082
7083 if (NS_WARN_IF(!mRedirectURI)NS_warn_if_impl(!mRedirectURI, "!mRedirectURI", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7083)
) {
7084 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)
;
7085 return NS_ERROR_FAILURE;
7086 }
7087
7088 return ContinueProcessRedirectionAfterFallback(NS_OK);
7089}
7090
7091nsresult nsHttpChannel::ContinueProcessRedirectionAfterFallback(nsresult rv) {
7092 // Kill the current cache entry if we are redirecting
7093 // back to ourself.
7094 bool redirectingBackToSameURI = false;
7095 if (mCacheEntry && LoadCacheEntryIsWriteOnly() &&
7096 NS_SUCCEEDED(mURI->Equals(mRedirectURI, &redirectingBackToSameURI))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mURI->Equals(mRedirectURI
, &redirectingBackToSameURI))), 1)))
&&
7097 redirectingBackToSameURI) {
7098 mCacheEntry->AsyncDoom(nullptr);
7099 }
7100
7101 // move the reference of the old location to the new one if the new
7102 // one has none.
7103 PropagateReferenceIfNeeded(mURI, mRedirectURI);
7104
7105 bool rewriteToGET =
7106 ShouldRewriteRedirectToGET(mRedirectType, mRequestHead.ParsedMethod());
7107
7108 // prompt if the method is not safe (such as POST, PUT, DELETE, ...)
7109 if (!rewriteToGET && !mRequestHead.IsSafeMethod()) {
7110 rv = PromptTempRedirect();
7111 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7112 }
7113
7114 uint32_t redirectFlags;
7115 if (nsHttp::IsPermanentRedirect(mRedirectType)) {
7116 redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
7117 } else {
7118 redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
7119 }
7120
7121 nsCOMPtr<nsIIOService> ioService;
7122 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
7123 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7124
7125 nsCOMPtr<nsIChannel> newChannel;
7126 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
7127 CloneLoadInfoForRedirect(mRedirectURI, redirectFlags);
7128
7129 // Propagate the unstripped redirect URI.
7130 redirectLoadInfo->SetUnstrippedURI(mUnstrippedRedirectURI);
7131
7132 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), mRedirectURI,
7133 redirectLoadInfo,
7134 nullptr, // PerformanceStorage
7135 nullptr, // aLoadGroup
7136 nullptr, // aCallbacks
7137 nsIRequest::LOAD_NORMAL, ioService);
7138 // If this fails, it usually means that the URI was invalid. Treat this as if
7139 // it were a CreateNewURI failure.
7140 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"
, 7140)
) {
7141 return NS_ERROR_CORRUPTED_CONTENT;
7142 }
7143
7144 rv = SetupReplacementChannel(mRedirectURI, newChannel, !rewriteToGET,
7145 redirectFlags);
7146 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7147
7148 // verify that this is a legal redirect
7149 mRedirectChannel = newChannel;
7150
7151 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
7152 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, redirectFlags);
7153
7154 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
7155
7156 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7157 AutoRedirectVetoNotifier notifier(this, rv);
7158 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
7159 }
7160
7161 return rv;
7162}
7163
7164nsresult nsHttpChannel::ContinueProcessRedirection(nsresult rv) {
7165 AutoRedirectVetoNotifier notifier(this, rv);
7166
7167 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)
7168 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)
;
7169 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7170
7171 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"
, 7171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRedirectChannel"
") (" "No redirect channel?" ")"); do { MOZ_CrashSequence(__null
, 7171); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
7172
7173 // Make sure to do this after we received redirect veto answer,
7174 // i.e. after all sinks had been notified
7175 mRedirectChannel->SetOriginalURI(mOriginalURI);
7176
7177 // XXX we used to talk directly with the script security manager, but that
7178 // should really be handled by the event sink implementation.
7179
7180 // begin loading the new channel
7181 rv = mRedirectChannel->AsyncOpen(mListener);
7182 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)
;
7183 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"
, 7183); return rv; } } while (false)
;
7184
7185 // close down this channel
7186 Cancel(NS_BINDING_REDIRECTED);
7187
7188 notifier.RedirectSucceeded();
7189
7190 ReleaseListeners();
7191
7192 return NS_OK;
7193}
7194
7195//-----------------------------------------------------------------------------
7196// nsHttpChannel <auth>
7197//-----------------------------------------------------------------------------
7198
7199NS_IMETHODIMPnsresult nsHttpChannel::OnAuthAvailable() {
7200 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)
;
7201
7202 // setting mAuthRetryPending flag and resuming the transaction
7203 // triggers process of throwing away the unauthenticated data already
7204 // coming from the network
7205 mIsAuthChannel = true;
7206 mAuthRetryPending = true;
7207 StoreProxyAuthPending(false);
7208 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)
;
7209 if (mTransactionPump) {
7210 Resume();
7211 }
7212
7213 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
7214 return CallOrWaitForResume(
7215 [](auto* self) { return self->RedirectToNewChannelForAuthRetry(); });
7216 }
7217
7218 return NS_OK;
7219}
7220
7221NS_IMETHODIMPnsresult nsHttpChannel::OnAuthCancelled(bool userCancel) {
7222 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)
;
7223 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"
, 7223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthRetryPending"
") (" "OnAuthCancelled should not be called twice" ")"); do {
MOZ_CrashSequence(__null, 7223); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7224
7225 if (mTransactionPump) {
7226 // If the channel is trying to authenticate to a proxy and
7227 // that was canceled we cannot show the http response body
7228 // from the 40x as that might mislead the user into thinking
7229 // it was a end host response instead of a proxy reponse.
7230 // This must check explicitly whether a proxy auth was being done
7231 // because we do want to show the content if this is an error from
7232 // the origin server.
7233 if (LoadProxyAuthPending()) Cancel(NS_ERROR_PROXY_CONNECTION_REFUSED);
7234
7235 // Make sure to process security headers before calling CallOnStartRequest.
7236 nsresult rv = ProcessCrossOriginSecurityHeaders();
7237 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7238 mStatus = rv;
7239 HandleAsyncAbort();
7240 return rv;
7241 }
7242
7243 // ensure call of OnStartRequest of the current listener here,
7244 // it would not be called otherwise at all
7245 rv = CallOnStartRequest();
7246
7247 // drop mAuthRetryPending flag and resume the transaction
7248 // this resumes load of the unauthenticated content data (which
7249 // may have been canceled if we don't want to show it)
7250 mAuthRetryPending = false;
7251 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)
;
7252 Resume();
7253
7254 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) mTransactionPump->Cancel(rv);
7255 }
7256
7257 StoreProxyAuthPending(false);
7258 return NS_OK;
7259}
7260
7261NS_IMETHODIMPnsresult nsHttpChannel::CloseStickyConnection() {
7262 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)
;
7263
7264 // Require we are between OnStartRequest and OnStopRequest, because
7265 // what we do here takes effect in OnStopRequest (not reusing the
7266 // connection for next authentication round).
7267 if (!LoadIsPending()) {
7268 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)
;
7269 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7271); MOZ_PretendNoReturn(); } while (0)
7270 "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"
, 7271); MOZ_PretendNoReturn(); } while (0)
7271 "effect")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7271); MOZ_PretendNoReturn(); } while (0)
;
7272 return NS_ERROR_UNEXPECTED;
7273 }
7274
7275 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"
, 7275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { MOZ_CrashSequence(__null, 7275); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7276 if (!mTransaction) {
7277 return NS_ERROR_UNEXPECTED;
7278 }
7279
7280 if (!(mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
7281 mTransaction->HasStickyConnection())) {
7282 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)
;
7283 return NS_OK;
7284 }
7285
7286 mTransaction->DontReuseConnection();
7287 return NS_OK;
7288}
7289
7290NS_IMETHODIMPnsresult nsHttpChannel::ConnectionRestartable(bool aRestartable) {
7291 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)
7292 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)
;
7293 StoreAuthConnectionRestartable(aRestartable);
7294 return NS_OK;
7295}
7296
7297//-----------------------------------------------------------------------------
7298// nsHttpChannel::nsISupports
7299//-----------------------------------------------------------------------------
7300
7301NS_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; }
7302bool nsHttpChannel::DispatchRelease() {
7303 if (NS_IsMainThread()) {
7304 return false;
7305 }
7306
7307 NS_DispatchToMainThread(
7308 NewNonOwningRunnableMethod("net::nsHttpChannel::Release", this,
7309 &nsHttpChannel::Release),
7310 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
7311
7312 return true;
7313}
7314
7315NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
7316nsHttpChannel::Release() {
7317 nsrefcnt count = mRefCnt - 1;
7318 if (DispatchRelease()) {
7319 // Redispatched to the main thread.
7320 return count;
7321 }
7322
7323 NS_IMPL_RELEASE_INHERITED_GUTS(nsHttpChannel, HttpBaseChannel)nsrefcnt r = HttpBaseChannel::Release(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<nsHttpChannel>) { NS_LogRelease
((this), (r), ("nsHttpChannel")); } return r
;
7324}
7325
7326NS_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"
, 7326); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
7327 NS_INTERFACE_MAP_ENTRY(nsIRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequest>)) foundInterface = static_cast
<nsIRequest*>(this); else
7328 NS_INTERFACE_MAP_ENTRY(nsIChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIChannel>)) foundInterface = static_cast
<nsIChannel*>(this); else
7329 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestObserver>)) foundInterface
= static_cast<nsIRequestObserver*>(this); else
7330 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIStreamListener>)) foundInterface
= static_cast<nsIStreamListener*>(this); else
7331 NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannel>)) foundInterface =
static_cast<nsIHttpChannel*>(this); else
7332 NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheInfoChannel>)) foundInterface
= static_cast<nsICacheInfoChannel*>(this); else
7333 NS_INTERFACE_MAP_ENTRY(nsICachingChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICachingChannel>)) foundInterface
= static_cast<nsICachingChannel*>(this); else
7334 NS_INTERFACE_MAP_ENTRY(nsIClassOfService)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIClassOfService>)) foundInterface
= static_cast<nsIClassOfService*>(this); else
7335 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel>)) foundInterface
= static_cast<nsIUploadChannel*>(this); else
7336 NS_INTERFACE_MAP_ENTRY(nsIFormPOSTActionChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIFormPOSTActionChannel>)) foundInterface
= static_cast<nsIFormPOSTActionChannel*>(this); else
7337 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel2>)) foundInterface
= static_cast<nsIUploadChannel2*>(this); else
7338 NS_INTERFACE_MAP_ENTRY(nsICacheEntryOpenCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheEntryOpenCallback>)) foundInterface
= static_cast<nsICacheEntryOpenCallback*>(this); else
7339 NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannelInternal>)) foundInterface
= static_cast<nsIHttpChannelInternal*>(this); else
7340 NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIResumableChannel>)) foundInterface
= static_cast<nsIResumableChannel*>(this); else
7341 NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsITransportEventSink>)) foundInterface
= static_cast<nsITransportEventSink*>(this); else
7342 NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsPriority>)) foundInterface
= static_cast<nsISupportsPriority*>(this); else
7343 NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProtocolProxyCallback>)) foundInterface
= static_cast<nsIProtocolProxyCallback*>(this); else
7344 NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProxiedChannel>)) foundInterface
= static_cast<nsIProxiedChannel*>(this); else
7345 NS_INTERFACE_MAP_ENTRY(nsIHttpAuthenticableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpAuthenticableChannel>)) foundInterface
= static_cast<nsIHttpAuthenticableChannel*>(this); else
7346 NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAsyncVerifyRedirectCallback>))
foundInterface = static_cast<nsIAsyncVerifyRedirectCallback
*>(this); else
7347 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableRequest>)) foundInterface
= static_cast<nsIThreadRetargetableRequest*>(this); else
7348 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableStreamListener>
)) foundInterface = static_cast<nsIThreadRetargetableStreamListener
*>(this); else
7349 NS_INTERFACE_MAP_ENTRY(nsIDNSListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDNSListener>)) foundInterface =
static_cast<nsIDNSListener*>(this); else
7350 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
7351 NS_INTERFACE_MAP_ENTRY(nsICorsPreflightCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICorsPreflightCallback>)) foundInterface
= static_cast<nsICorsPreflightCallback*>(this); else
7352 NS_INTERFACE_MAP_ENTRY(nsIRequestTailUnblockCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestTailUnblockCallback>)) foundInterface
= static_cast<nsIRequestTailUnblockCallback*>(this); else
7353 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
7354 NS_INTERFACE_MAP_ENTRY(nsIEarlyHintObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIEarlyHintObserver>)) foundInterface
= static_cast<nsIEarlyHintObserver*>(this); else
7355NS_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; }
7356
7357//-----------------------------------------------------------------------------
7358// nsHttpChannel::nsIRequest
7359//-----------------------------------------------------------------------------
7360
7361NS_IMETHODIMPnsresult nsHttpChannel::SetCanceledReason(const nsACString& aReason) {
7362 return SetCanceledReasonImpl(aReason);
7363}
7364
7365NS_IMETHODIMPnsresult nsHttpChannel::GetCanceledReason(nsACString& aReason) {
7366 return GetCanceledReasonImpl(aReason);
7367}
7368
7369NS_IMETHODIMPnsresult
7370nsHttpChannel::CancelWithReason(nsresult aStatus, const nsACString& aReason) {
7371 return CancelWithReasonImpl(aStatus, aReason);
7372}
7373
7374NS_IMETHODIMPnsresult
7375nsHttpChannel::Cancel(nsresult status) {
7376 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", 7376
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7377 // We should never have a pump open while a CORS preflight is in progress.
7378 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"
, 7378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7378); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7379#ifdef DEBUG1
7380 // We want to perform this check only when the chanel is being cancelled the
7381 // first time with a URL classifier blocking error code. If mStatus is
7382 // already set to such an error code then Cancel() may be called for some
7383 // other reason, for example because we've received notification about our
7384 // parent process side channel being canceled, in which case we cannot expect
7385 // that CancelByURLClassifier() would have handled this case.
7386 if (ChannelClassifierUtils::IsClassifierBlockingErrorCode(status) &&
7387 !ChannelClassifierUtils::IsClassifierBlockingErrorCode(mStatus)) {
7388 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"
, 7390, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
7389 " 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"
, 7390, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
7390 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"
, 7390, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
;
7391 }
7392#endif
7393
7394 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)
7395 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)
;
7396 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)
7397 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)
;
7398
7399 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", 7401
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7401); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7400 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", 7401
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7401); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7401 !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", 7401
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7401); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7402
7403 mEarlyHintObserver = nullptr;
7404 mWebTransportSessionEventListener = nullptr;
7405
7406 if (mCanceled) {
7407 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)
;
7408 return NS_OK;
7409 }
7410
7411 LogCallingScriptLocation(this);
7412
7413 if (LoadWaitingForRedirectCallback()) {
7414 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)
;
7415 }
7416
7417 return CancelInternal(status);
7418}
7419
7420NS_IMETHODIMPnsresult
7421nsHttpChannel::CancelByURLClassifier(nsresult aErrorCode) {
7422 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", 7422
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 7422); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7423 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", 7423
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7423); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7424 // We should never have a pump open while a CORS preflight is in progress.
7425 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"
, 7425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7425); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7426
7427 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)
;
7428
7429 if (mCanceled) {
7430 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)
;
7431 return NS_OK;
7432 }
7433
7434 // We are being canceled by the channel classifier because of tracking
7435 // protection, but we haven't yet had a chance to dispatch the
7436 // "http-on-modify-request" notifications yet (this would normally be
7437 // done in PrepareToConnect()). So do that now, before proceeding to
7438 // cancel.
7439 //
7440 // Note that running these observers can itself result in the channel
7441 // being canceled. In that case, we accept that cancelation code as
7442 // the cause of the cancelation, as if the classification of the channel
7443 // would have occurred past this point!
7444
7445 // notify "http-on-modify-request" observers
7446 CallOnModifyRequestObservers();
7447
7448 // Check if request was cancelled during on-modify-request
7449 if (mCanceled) {
7450 return mStatus;
7451 }
7452
7453 if (mSuspendCount) {
7454 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)
;
7455 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", 7455
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume" ")"
); do { MOZ_CrashSequence(__null, 7455); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7456 StoreChannelClassifierCancellationPending(1);
7457 mCallOnResume = [aErrorCode](nsHttpChannel* self) {
7458 self->HandleContinueCancellingByURLClassifier(aErrorCode);
7459 return NS_OK;
7460 };
7461 return NS_OK;
7462 }
7463
7464 // Check to see if we should redirect this channel elsewhere by
7465 // nsIHttpChannel.redirectTo API request
7466 if (mAPIRedirectTo) {
7467 StoreChannelClassifierCancellationPending(1);
7468 return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
7469 }
7470
7471 return CancelInternal(aErrorCode);
7472}
7473
7474void nsHttpChannel::ContinueCancellingByURLClassifier(nsresult aErrorCode) {
7475 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", 7475
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 7475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7476 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", 7476
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7477 // We should never have a pump open while a CORS preflight is in progress.
7478 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"
, 7478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7478); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7479
7480 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)
;
7481 if (mCanceled) {
7482 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)
;
7483 return;
7484 }
7485
7486 // Check to see if we should redirect this channel elsewhere by
7487 // nsIHttpChannel.redirectTo API request
7488 if (mAPIRedirectTo) {
7489 (void)AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
7490 return;
7491 }
7492
7493 (void)CancelInternal(aErrorCode);
7494}
7495
7496nsresult nsHttpChannel::CancelInternal(nsresult status) {
7497 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)
;
7498 bool channelClassifierCancellationPending =
7499 !!LoadChannelClassifierCancellationPending();
7500 if (ChannelClassifierUtils::IsClassifierBlockingErrorCode(status)) {
7501 StoreChannelClassifierCancellationPending(0);
7502 }
7503
7504 mEarlyHintObserver = nullptr;
7505 mWebTransportSessionEventListener = nullptr;
7506 mCanceled = true;
7507 mStatus = NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) ? status : NS_ERROR_ABORT;
7508
7509 // If ORB blocked this response, doom the entry that was committed to the
7510 // cache before the (asynchronous) block decision, so it can't be reused
7511 // later (e.g. a navigation consuming a prefetched, ORB-blocked cross-origin
7512 // document). See bug 2045809.
7513 if (mChannelBlockedByOpaqueResponse && mORBValidationCacheEntry) {
7514 mORBValidationCacheEntry->AsyncDoom(nullptr);
7515 mORBValidationCacheEntry = nullptr;
7516 }
7517
7518 // If we're waiting for LNA permission result and the channel is being
7519 // cancelled, we need to call OnPermissionPromptResult with permission denied
7520 // to resume the channel properly
7521 if (mWaitingForLNAPermission) {
7522 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)
7523 ("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)
7524 "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)
7525 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
7526 // Determine permission key dynamically from transaction
7527 const nsACString& permissionKey =
7528 (mTransaction && mTransaction->GetTargetIPAddressSpace() ==
7529 nsILoadInfo::IPAddressSpace::Local)
7530 ? LOOPBACK_NETWORK_PERMISSION_KEY
7531 : LOCAL_NETWORK_PERMISSION_KEY;
7532 OnPermissionPromptResult(false, permissionKey);
7533 return NS_OK;
7534 }
7535
7536 if (LoadUsedNetwork() && !mReportedNEL) {
7537 MaybeGenerateNELReport();
7538 }
7539
7540 // We don't want the content process to see any header values
7541 // when the request is blocked by ORB
7542 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref &&
7543 mResponseHead) {
7544 mResponseHead->ClearHeaders();
7545 }
7546
7547 if (mLastStatusReported && !mEndMarkerAdded &&
7548 profiler_thread_is_being_profiled_for_markers()) {
7549 // These do allocations/frees/etc; avoid if not active
7550 // mLastStatusReported can be null if Cancel is called before we added the
7551 // start marker.
7552 mEndMarkerAdded = true;
7553
7554 nsAutoCString requestMethod;
7555 GetRequestMethod(requestMethod);
7556
7557 int32_t priority = PRIORITY_NORMAL;
7558 GetPriority(&priority);
7559
7560 uint64_t size = 0;
7561 GetEncodedBodySize(&size);
7562
7563 profiler_add_network_marker(
7564 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_CANCEL,
7565 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
7566 mLoadInfo->GetInnerWindowID(),
7567 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
7568 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
7569 &mTransactionTimings, std::move(mSource));
7570 }
7571
7572 // If we don't have mTransactionPump and mCachePump, we need to call
7573 // AsyncAbort to make sure this channel's listener got notified.
7574 bool needAsyncAbort = !mTransactionPump && !mCachePump;
7575
7576 if (mProxyRequest) mProxyRequest->Cancel(status);
7577 CancelNetworkRequest(status);
7578 mCacheInputStream.CloseAndRelease();
7579 if (mCachePump) mCachePump->Cancel(status);
7580 if (mAuthProvider) mAuthProvider->Cancel(status);
7581 if (mPreflightChannel) mPreflightChannel->Cancel(status);
7582 if (mRequestContext && mOnTailUnblock) {
7583 mOnTailUnblock = nullptr;
7584 mRequestContext->CancelTailedRequest(this);
7585 CloseCacheEntry(false);
7586 needAsyncAbort = false;
7587 (void)AsyncAbort(status);
7588 } else if (channelClassifierCancellationPending) {
7589 // If mCallOnResume is not null here, it's set in
7590 // nsHttpChannel::CancelByURLClassifier. We can override mCallOnResume since
7591 // mCanceled is true and nsHttpChannel::ContinueCancellingByURLClassifier
7592 // does nothing.
7593 if (mCallOnResume) {
7594 mCallOnResume = nullptr;
7595 }
7596 // If we're coming from an asynchronous path when canceling a channel due
7597 // to safe-browsing protection, we need to AsyncAbort the channel now.
7598 needAsyncAbort = false;
7599 (void)AsyncAbort(status);
7600 }
7601
7602 // If we suspended after examining the response to await asynchronous
7603 // tracking-protection annotation (bug 2030021), a cancel while suspended
7604 // would otherwise defer the terminal teardown below (CloseCacheEntry /
7605 // AsyncAbort) to a Resume() that may never arrive. For a cache writer that
7606 // leaves the entry perpetually "being written" -- its output stream never
7607 // closed and the entry never doomed -- wedging every later same-URL
7608 // revalidating consumer forever (bug 2052908). Undo the annotation
7609 // suspension now so the cancelled pump delivers OnStopRequest and the
7610 // write-only entry is closed/doomed normally. Safe if we only primed but
7611 // never actually suspended.
7612 CancelSuspendOrResumeAfterExamineResponse();
7613
7614 // If suspended waiting for dictionary prefetch, unblock it so the channel
7615 // can proceed to cleanup. The prefetch callback may never fire, so we must
7616 // not rely on it to call Resume().
7617 if (mSuspendedForDictionary) {
7618 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)
7619 ("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)
7620 "[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)
7621 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
7622 mSuspendedForDictionary = false;
7623 mCallOnResume = nullptr;
7624 // Null out the already-cancelled pumps so Resume() won't re-trigger
7625 // their OnStopRequest before AsyncAbort's DoNotifyListener can call
7626 // OnStartRequest on our listener.
7627 mTransactionPump = nullptr;
7628 mCachePump = nullptr;
7629 Resume();
7630 needAsyncAbort = true;
7631 }
7632
7633 // If we already have mCallOnResume, AsyncAbort will be called in
7634 // ResumeInternal.
7635 if (needAsyncAbort && !mCallOnResume && !mSuspendCount) {
7636 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)
;
7637 CloseCacheEntry(false);
7638 (void)AsyncAbort(status);
7639 }
7640 return NS_OK;
7641}
7642
7643void nsHttpChannel::CancelNetworkRequest(nsresult aStatus) {
7644 if (mTransaction) {
7645 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, aStatus);
7646 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7647 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)
;
7648 }
7649 }
7650 if (mTransactionPump) mTransactionPump->Cancel(aStatus);
7651
7652 mEarlyHintObserver = nullptr;
7653 mWebTransportSessionEventListener = nullptr;
7654}
7655
7656NS_IMETHODIMPnsresult
7657nsHttpChannel::Suspend() {
7658 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", 7658
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7658); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7659 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"
, 7659); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7660
7661 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
)
7662 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
)
;
7663 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)
;
7664 LogCallingScriptLocation(this);
7665
7666 ++mSuspendCount;
7667
7668 if (mSuspendCount == 1) {
7669 mSuspendTimestamp = TimeStamp::NowLoRes();
7670
7671 // Start timer to detect if we're suspended too long
7672 // This helps unblock waiting cache listeners when a channel is suspended
7673 // for an unreasonably long time.
7674 uint32_t delay = StaticPrefs::network_cache_suspended_writer_delay_ms();
7675 if (!mSuspendTimer && delay) {
7676 mSuspendTimer = NS_NewTimer();
7677 }
7678
7679 if (mSuspendTimer && delay) {
7680 RefPtr<TimerCallback> timerCallback = new TimerCallback(this);
7681 mSuspendTimer->InitWithCallback(timerCallback, delay,
7682 nsITimer::TYPE_ONE_SHOT);
7683 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)
;
7684 }
7685 }
7686
7687 nsresult rvTransaction = NS_OK;
7688 if (mTransactionPump) {
7689 rvTransaction = mTransactionPump->Suspend();
7690 }
7691 nsresult rvCache = NS_OK;
7692 if (mCachePump) {
7693 rvCache = mCachePump->Suspend();
7694 }
7695
7696 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
7697}
7698
7699// static
7700void nsHttpChannel::StaticSuspend(nsHttpChannel* aChan) { aChan->Suspend(); }
7701
7702NS_IMETHODIMPnsresult
7703nsHttpChannel::Resume() {
7704 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", 7704
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7704); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7705 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"
, 7705); return NS_ERROR_UNEXPECTED; } } while (false)
;
7706
7707 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::Resume", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7708( "nsHttpChannel::Resume"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7708 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7708( "nsHttpChannel::Resume"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7709 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)
;
7710 LogCallingScriptLocation(this);
7711
7712 if (--mSuspendCount == 0) {
7713 mSuspendTotalTime += TimeStamp::NowLoRes() - mSuspendTimestamp;
7714
7715 // Cancel suspend timer since we're resuming
7716 if (mSuspendTimer) {
7717 mSuspendTimer->Cancel();
7718 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)
;
7719 }
7720
7721 // Reset bypass flag since the writer is resuming
7722 if (mBypassCacheWriterSet && mCacheEntry) {
7723 mCacheEntry->SetBypassWriterLock(false);
7724 mBypassCacheWriterSet = false;
7725 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)
;
7726 }
7727
7728 if (mCallOnResume) {
7729 // Resume the interrupted procedure first, then resume
7730 // the pump to continue process the input stream.
7731 // Any newly created pump MUST be suspended to prevent calling
7732 // its OnStartRequest before OnStopRequest of any pre-existing
7733 // pump. AsyncResumePending ensures that.
7734 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", 7734
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7734); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7735 StoreAsyncResumePending(1);
7736
7737 std::function<nsresult(nsHttpChannel*)> callOnResume = nullptr;
7738 std::swap(callOnResume, mCallOnResume);
7739
7740 RefPtr<nsHttpChannel> self(this);
7741 nsCOMPtr<nsIRequest> transactionPump = mTransactionPump;
7742 RefPtr<nsInputStreamPump> cachePump = mCachePump;
7743
7744 nsresult rv = NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7745 "nsHttpChannel::CallOnResume",
7746 [callOnResume{std::move(callOnResume)}, self{std::move(self)},
7747 transactionPump{std::move(transactionPump)},
7748 cachePump{std::move(cachePump)}]() {
7749 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"
, 7749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7749); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7750 nsresult rv = self->CallOrWaitForResume(callOnResume);
7751 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7752 self->CloseCacheEntry(false);
7753 (void)self->AsyncAbort(rv);
7754 }
7755 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"
, 7755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7755); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7756
7757 self->StoreAsyncResumePending(0);
7758
7759 // And now actually resume the previously existing pumps.
7760 if (transactionPump) {
7761 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)
7762 ("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)
7763 "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)
7764 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)
;
7765 transactionPump->Resume();
7766 }
7767 if (cachePump) {
7768 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)
7769 ("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)
7770 "%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)
7771 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)
;
7772 cachePump->Resume();
7773 }
7774
7775 // Any newly created pumps were suspended once because of
7776 // AsyncResumePending. Problem is that the stream listener
7777 // notification is already pending in the queue right now, because
7778 // AsyncRead doesn't (regardless if called after Suspend) respect
7779 // the suspend coutner and the right order would not be preserved.
7780 // Hence, we do another dispatch round to actually Resume after
7781 // the notification from the original pump.
7782 if (transactionPump != self->mTransactionPump &&
7783 self->mTransactionPump) {
7784 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)
7785 ("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)
7786 "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)
7787 "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)
7788 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)
;
7789
7790 nsCOMPtr<nsIRequest> pump = self->mTransactionPump;
7791 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7792 "nsHttpChannel::CallOnResume new transaction",
7793 [pump{std::move(pump)}]() { pump->Resume(); }));
7794 }
7795 if (cachePump != self->mCachePump && self->mCachePump) {
7796 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)
7797 ("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)
7798 "%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)
7799 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)
;
7800
7801 RefPtr<nsInputStreamPump> pump = self->mCachePump;
7802 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7803 "nsHttpChannel::CallOnResume new pump",
7804 [pump{std::move(pump)}]() { pump->Resume(); }));
7805 }
7806 }));
7807 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"
, 7807); return rv; } } while (false)
;
7808 return rv;
7809 }
7810 }
7811
7812 nsresult rvTransaction = NS_OK;
7813 if (mTransactionPump) {
7814 rvTransaction = mTransactionPump->Resume();
7815 }
7816
7817 nsresult rvCache = NS_OK;
7818 if (mCachePump) {
7819 rvCache = mCachePump->Resume();
7820 }
7821
7822 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
7823}
7824
7825//-----------------------------------------------------------------------------
7826// nsHttpChannel::nsIChannel
7827//-----------------------------------------------------------------------------
7828
7829NS_IMETHODIMPnsresult
7830nsHttpChannel::GetSecurityInfo(nsITransportSecurityInfo** securityInfo) {
7831 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"
, 7831); return NS_ERROR_INVALID_POINTER; } } while (false)
;
7832 *securityInfo = do_AddRef(mSecurityInfo).take();
7833 return NS_OK;
7834}
7835
7836// If any of the functions that AsyncOpen calls returns immediately an error
7837// AsyncAbort(which calls onStart/onStopRequest) does not need to be call.
7838// To be sure that they are not call ReleaseListeners() is called.
7839// If AsyncOpen returns NS_OK, after that point AsyncAbort must be called on
7840// any error.
7841NS_IMETHODIMPnsresult
7842nsHttpChannel::AsyncOpen(nsIStreamListener* aListener) {
7843 // doContentSecurityCheck and OnOpeningRequest fire observers that may
7844 // spin nested event loops; hold a strong ref to this.
7845 RefPtr<nsHttpChannel> self(this);
7846
7847 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpen", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7848( "nsHttpChannel::AsyncOpen"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7848 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7848( "nsHttpChannel::AsyncOpen"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7849 nsCOMPtr<nsIStreamListener> listener = aListener;
7850 nsresult rv =
7851 nsContentSecurityManager::doContentSecurityCheck(this, listener);
7852 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"
, 7852)
) {
7853 ReleaseListeners();
7854 return rv;
7855 }
7856
7857 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"
, 7864); 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, 7864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7858 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"
, 7864); 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, 7864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7859 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"
, 7864); 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, 7864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7860 (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"
, 7864); 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, 7864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7861 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"
, 7864); 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, 7864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7862 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"
, 7864); 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, 7864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7863 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"
, 7864); 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, 7864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7864 "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"
, 7864); 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, 7864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7865
7866 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
)
;
7867 mOpenerCallingScriptLocation = CallingScriptLocationString();
7868 LogCallingScriptLocation(this, mOpenerCallingScriptLocation);
7869 NS_CompareLoadInfoAndLoadContext(this);
7870
7871#ifdef DEBUG1
7872 AssertPrivateBrowsingId();
7873#endif
7874
7875 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", 7875
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
7876 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"
, 7876); return NS_ERROR_IN_PROGRESS; } } while (false)
;
7877 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"
, 7877); return NS_ERROR_ALREADY_OPENED; } } while (false)
;
7878
7879 if (mCanceled) {
7880 ReleaseListeners();
7881 return NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) ? mStatus : NS_ERROR_FAILURE;
7882 }
7883
7884 if (MaybeWaitForUploadStreamNormalization(listener, nullptr)) {
7885 return NS_OK;
7886 }
7887
7888 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", 7888
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7888); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7889
7890 if (!gHttpHandler->Active()) {
7891 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)
;
7892 ReleaseListeners();
7893 return NS_ERROR_NOT_AVAILABLE;
7894 }
7895
7896 rv = NS_CheckPortSafety(mURI);
7897 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7898 ReleaseListeners();
7899 return rv;
7900 }
7901
7902 // If no one called SetLoadGroup or SetNotificationCallbacks, the private
7903 // state has not been updated on PrivateBrowsingChannel (which we derive
7904 // from) Same if the loadinfo has changed since the creation of the channel.
7905 // Hence, we have to call UpdatePrivateBrowsing() here
7906 UpdatePrivateBrowsing();
7907
7908 AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(this);
7909
7910 // Recalculate the default userAgent header after the AntiTrackingInfo gets
7911 // updated because we can only know whether the site is exempted from
7912 // fingerprinting protection after we have the AntiTracking Info.
7913 //
7914 // Note that we don't recalculate the header if it has been modified since the
7915 // channel was created because we want to preserve the modified header.
7916 if (!LoadIsUserAgentHeaderModified()) {
7917 rv = mRequestHead.SetHeader(
7918 nsHttp::User_Agent,
7919 gHttpHandler->UserAgent(nsContentUtils::ShouldResistFingerprinting(
7920 this, RFPTarget::HttpUserAgent)),
7921 false, nsHttpHeaderArray::eVarietyRequestEnforceDefault);
7922 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"
, 7922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 7922); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7923 }
7924
7925 if (WaitingForTailUnblock()) {
7926 // This channel is marked as Tail and is part of a request context
7927 // that has positive number of non-tailed requestst, hence this channel
7928 // has been put to a queue.
7929 // When tail is unblocked, OnTailUnblock on this channel will be called
7930 // to continue AsyncOpen.
7931 mListener = listener;
7932 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", 7932
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 7932); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7933 mOnTailUnblock = &nsHttpChannel::AsyncOpenOnTailUnblock;
7934
7935 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)
;
7936 return NS_OK;
7937 }
7938
7939 // Remember the cookie header that was set, if any
7940 nsAutoCString cookieHeader;
7941 if (NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::Cookie, cookieHeader))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::Cookie, cookieHeader))), 1)))
) {
7942 // if this is a cache revalidaing channel (mIsStaleRevalidation), then this
7943 // represents both user cookies and cookies from cookieService
7944 mUserSetCookieHeader = std::move(cookieHeader);
7945 }
7946
7947 // Set user agent override, do so before OnOpeningRequest notification
7948 // since we want to allow consumers of that notification change or remove
7949 // the User-Agent request header.
7950 HttpBaseChannel::SetDocshellUserAgentOverride();
7951
7952 // After we notify any observers (on-opening-request, loadGroup, etc) we
7953 // must return NS_OK and return any errors asynchronously via
7954 // OnStart/OnStopRequest. Observers may add a reference to the channel
7955 // and expect to get OnStopRequest so they know when to drop the reference,
7956 // etc.
7957
7958 // notify "http-on-opening-request" observers, but not if this is a redirect
7959 if (!(mLoadFlags & LOAD_REPLACE)) {
7960 gHttpHandler->OnOpeningRequest(this);
7961 }
7962
7963 StoreIsPending(true);
7964 StoreWasOpened(true);
7965
7966 mListener = std::move(listener);
7967
7968 if (nsIOService::UseSocketProcess() &&
7969 !gIOService->IsSocketProcessLaunchComplete()) {
7970 RefPtr<nsHttpChannel> self = this;
7971 gIOService->CallOrWaitForSocketProcess(
7972 [self]() { self->AsyncOpenFinal(TimeStamp::Now()); });
7973 return NS_OK;
7974 }
7975
7976 AsyncOpenFinal(TimeStamp::Now());
7977
7978 return NS_OK;
7979}
7980
7981void nsHttpChannel::AsyncOpenFinal(TimeStamp aTimeStamp) {
7982 // We save this timestamp from outside of the if block in case we enable the
7983 // profiler after AsyncOpen().
7984 mLastStatusReported = TimeStamp::Now();
7985 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpenFinal", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7986( "nsHttpChannel::AsyncOpenFinal"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7986 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7986( "nsHttpChannel::AsyncOpenFinal"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7987 if (profiler_thread_is_being_profiled_for_markers()) {
7988 nsAutoCString requestMethod;
7989 GetRequestMethod(requestMethod);
7990
7991 profiler_add_network_marker(
7992 mURI, requestMethod, mPriority, mChannelId, NetworkLoadType::LOAD_START,
7993 mChannelCreationTimestamp, mLastStatusReported, 0, mCacheDisposition,
7994 mLoadInfo->GetInnerWindowID(),
7995 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
7996 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch());
7997 }
7998
7999 // Added due to PauseTask/DelayHttpChannel
8000 if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
8001
8002 // record asyncopen time unconditionally and clear it if we
8003 // don't want it after OnModifyRequest() weighs in. But waiting for
8004 // that to complete would mean we don't include proxy resolution in the
8005 // timing.
8006 if (!LoadAsyncOpenTimeOverriden()) {
8007 mAsyncOpenTime = aTimeStamp;
8008 }
8009
8010 // Remember we have Authorization header set here. We need to check on it
8011 // just once and early, AsyncOpen is the best place.
8012 StoreCustomAuthHeader(mRequestHead.HasHeader(nsHttp::Authorization));
8013
8014 bool willCallback = false;
8015 // We are about to do an async lookup to check if the URI is a tracker. If
8016 // yes, this channel will be canceled by channel classifier. Chances are the
8017 // lookup is not needed so CheckIsTrackerWithLocalTable() will return an
8018 // error and then we can MaybeResolveProxyAndBeginConnect() right away.
8019 // We skip the check in case this is an internal redirected channel
8020 if (NS_ShouldClassifyChannel(this, ClassifyType::ETP)) {
8021 RefPtr<nsHttpChannel> self = this;
8022 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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8023 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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8024 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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8025 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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8026 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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8027
8028 // 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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8029 // 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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8030 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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8031
8032 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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8033 }))((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"
, 8026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8026); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
;
8034 }
8035
8036 if (!willCallback) {
8037 // We can do MaybeResolveProxyAndBeginConnect immediately if
8038 // CheckIsTrackerWithLocalTable is failed. Note that we don't need to
8039 // handle the failure because BeginConnect() will return synchronously and
8040 // the caller will be responsible for handling it.
8041 MaybeResolveProxyAndBeginConnect();
8042 }
8043}
8044
8045void nsHttpChannel::MaybeResolveProxyAndBeginConnect() {
8046 nsresult rv;
8047
8048 // The common case for HTTP channels is to begin proxy resolution and return
8049 // at this point. The only time we know mProxyInfo already is if we're
8050 // proxying a non-http protocol like ftp. We don't need to discover proxy
8051 // settings if we are never going to make a network connection.
8052 if (!mProxyInfo &&
8053 !(mLoadFlags & (LOAD_ONLY_FROM_CACHE | LOAD_NO_NETWORK_IO)) &&
8054 !BypassProxy()) {
8055 nsCOMPtr<nsIProtocolProxyService> pps =
8056 mozilla::components::ProtocolProxy::Service();
8057 nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
8058 if (pps2 && pps2->IsEffectivelyDirect()) {
8059 mozilla::glean::networking::proxy_fast_path_used.Add(1);
8060 MaybeStartDNSPrefetch();
8061 } else if (NS_SUCCEEDED(ResolveProxy())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ResolveProxy())),
1)))
) {
8062 return;
8063 }
8064 }
8065
8066 if (!gHttpHandler->Active()) {
8067 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)
8068 ("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)
8069 "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)
8070 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
8071 rv = NS_ERROR_NOT_AVAILABLE;
8072 } else {
8073 rv = BeginConnect();
8074 }
8075 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8076 CloseCacheEntry(false);
8077 (void)AsyncAbort(rv);
8078 }
8079}
8080
8081nsresult nsHttpChannel::AsyncOpenOnTailUnblock() {
8082 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpenOnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject8083( "nsHttpChannel::AsyncOpenOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
8083 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject8083( "nsHttpChannel::AsyncOpenOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
8084 return AsyncOpen(mListener);
8085}
8086
8087already_AddRefed<nsChannelClassifier>
8088nsHttpChannel::GetOrCreateChannelClassifier() {
8089 if (!mChannelClassifier) {
8090 mChannelClassifier = new nsChannelClassifier(this);
8091 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)
8092 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)
;
8093 }
8094
8095 RefPtr<nsChannelClassifier> classifier = mChannelClassifier;
8096 return classifier.forget();
8097}
8098
8099nsIHttpChannelInternal::ProxyDNSStrategy
8100nsHttpChannel::ComputeProxyDNSStrategy() {
8101 // When network_dns_force_use_https_rr is true, return DNS_PREFETCH_ORIGIN.
8102 // This ensures that we always perform HTTPS RR query.
8103 nsCOMPtr<nsProxyInfo> proxyInfo(static_cast<nsProxyInfo*>(mProxyInfo.get()));
8104 if (!proxyInfo || StaticPrefs::network_dns_force_use_https_rr()) {
8105 return nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN;
8106 }
8107
8108 // If the proxy is not to perform name resolution itself.
8109 return GetProxyDNSStrategyHelper(proxyInfo->Type(), proxyInfo->Flags());
8110}
8111
8112NS_IMETHODIMPnsresult
8113nsHttpChannel::GetProxyDNSStrategy(
8114 nsIHttpChannelInternal::ProxyDNSStrategy* aStrategy) {
8115 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", 8115
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
8116 *aStrategy = ComputeProxyDNSStrategy();
8117 return NS_OK;
8118}
8119
8120// BeginConnect() SHOULD NOT call AsyncAbort(). AsyncAbort will be called by
8121// functions that called BeginConnect if needed. Only
8122// MaybeResolveProxyAndBeginConnect and OnProxyAvailable ever call
8123// BeginConnect.
8124nsresult nsHttpChannel::BeginConnect() {
8125 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)
;
8126
8127 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::BeginConnect", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject8128( "nsHttpChannel::BeginConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
8128 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject8128( "nsHttpChannel::BeginConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
8129 nsresult rv;
8130
8131 // It is the caller's responsibility to not call us late in shutdown.
8132 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", 8132
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gHttpHandler->Active()"
")"); do { MOZ_CrashSequence(__null, 8132); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8133
8134 // Construct connection info object
8135 nsAutoCString host;
8136 nsAutoCString scheme;
8137 int32_t port = -1;
8138 bool isHttps = mURI->SchemeIs("https");
8139
8140 rv = mURI->GetScheme(scheme);
8141 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiHost(host);
8142 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetPort(&port);
8143 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiSpec(mSpec);
8144 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8145 return rv;
8146 }
8147
8148 // Just a warning here because some nsIURIs do not implement this method.
8149 (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", 8149
)
;
8150
8151 // Reject the URL if it doesn't specify a host
8152 if (host.IsEmpty()) {
8153 rv = NS_ERROR_MALFORMED_URI;
8154 return rv;
8155 }
8156 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)
;
8157 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)
;
8158
8159 nsCOMPtr<nsProxyInfo> proxyInfo;
8160 if (mProxyInfo) proxyInfo = do_QueryInterface(mProxyInfo);
8161
8162 if (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) {
8163 if (!proxyInfo) {
8164 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)
;
8165 return NS_ERROR_FAILURE;
8166 }
8167
8168 if (!proxyInfo->IsHTTP() && !proxyInfo->IsHTTPS()) {
8169 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)
;
8170 return NS_ERROR_FAILURE;
8171 }
8172 }
8173
8174 mRequestHead.SetHTTPS(isHttps);
8175 mRequestHead.SetOrigin(scheme, host, port);
8176
8177 AddStorageAccessHeadersToRequest();
8178 SetOriginHeader();
8179 SetDoNotTrack();
8180 SetGlobalPrivacyControl();
8181
8182 OriginAttributes originAttributes;
8183 // Regular principal in case we have a proxy.
8184 if (proxyInfo &&
8185 !StaticPrefs::privacy_partition_network_state_connection_with_proxy()) {
8186 StoragePrincipalHelper::GetOriginAttributes(
8187 this, originAttributes, StoragePrincipalHelper::eRegularPrincipal);
8188 } else {
8189 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
8190 this, originAttributes);
8191 }
8192
8193 // Adjust mCaps according to our request headers:
8194 // - If "Connection: close" is set as a request header, then do not bother
8195 // trying to establish a keep-alive connection.
8196 if (mRequestHead.HasHeaderValue(nsHttp::Connection, "close")) {
8197 mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE(1 << 0));
8198 StoreAllowHttp3(false);
8199 }
8200
8201 gHttpHandler->MaybeAddAltSvcForTesting(mURI, mUsername, mPrivateBrowsing,
8202 mCallbacks, originAttributes);
8203
8204 RefPtr<nsHttpConnectionInfo> connInfo;
8205#ifdef FUZZING
8206 if (StaticPrefs::fuzzing_necko_http3()) {
8207 connInfo =
8208 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8209 originAttributes, host, port, true);
8210 } else {
8211#endif
8212 if (mWebTransportSessionEventListener) {
8213 connInfo =
8214 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8215 originAttributes, isHttps, true, true);
8216 bool dedicated = true;
8217 nsresult rv;
8218 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
8219 do_QueryInterface(mWebTransportSessionEventListener, &rv);
8220 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"
, 8220); return rv; } } while (false)
;
8221 nsIWebTransport::HTTPVersion httpVersion;
8222 (void)wtconSettings->GetHttpVersion(&httpVersion);
8223 if (httpVersion == nsIWebTransport::HTTPVersion::h2) {
8224 connInfo =
8225 new nsHttpConnectionInfo(host, port, "h2"_ns, mUsername, proxyInfo,
8226 originAttributes, isHttps, false, true);
8227 } else {
8228 connInfo =
8229 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8230 originAttributes, isHttps, true, true);
8231 }
8232 wtconSettings->GetDedicated(&dedicated);
8233 if (dedicated) {
8234 connInfo = connInfo->Mutate()
8235 .SetWebTransportId(
8236 nsHttpConnectionInfo::GenerateNewWebTransportId())
8237 .Finalize();
8238 }
8239 } else {
8240 connInfo = new nsHttpConnectionInfo(host, port, ""_ns, mUsername,
8241 proxyInfo, originAttributes, isHttps);
8242 }
8243#ifdef FUZZING
8244 }
8245#endif
8246
8247 bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
8248
8249 bool http3Allowed = Http3Allowed();
8250 if (!http3Allowed) {
8251 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
8252 }
8253
8254 RefPtr<AltSvcMapping> mapping;
8255 if (!mConnectionInfo && LoadAllowAltSvc() && // per channel
8256 !mWebTransportSessionEventListener && (http2Allowed || http3Allowed) &&
8257 !(mLoadFlags & LOAD_FRESH_CONNECTION) &&
8258 AltSvcMapping::AcceptableProxy(proxyInfo) &&
8259 (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
8260 (mapping = gHttpHandler->GetAltServiceMapping(
8261 scheme, host, port, mPrivateBrowsing, originAttributes, http2Allowed,
8262 http3Allowed))) {
8263 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)
8264 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)
8265 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)
;
8266
8267 if (!(mLoadFlags & LOAD_ANONYMOUS) && !mPrivateBrowsing) {
8268 nsAutoCString altUsedLine(mapping->AlternateHost());
8269 bool defaultPort =
8270 mapping->AlternatePort() ==
8271 (isHttps ? NS_HTTPS_DEFAULT_PORT443 : NS_HTTP_DEFAULT_PORT80);
8272 if (!defaultPort) {
8273 altUsedLine.AppendLiteral(":");
8274 altUsedLine.AppendInt(mapping->AlternatePort());
8275 }
8276 // Like what we did for 'Authorization' header, we need to do the same for
8277 // 'Alt-Used' for avoiding this header being shown in the ServiceWorker
8278 // FetchEvent.
8279 (void)mRequestHead.ClearHeader(nsHttp::Alternate_Service_Used);
8280 rv = mRequestHead.SetHeader(nsHttp::Alternate_Service_Used, altUsedLine,
8281 false,
8282 nsHttpHeaderArray::eVarietyRequestDefault);
8283 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"
, 8283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 8283); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8284 }
8285
8286 nsCOMPtr<nsIConsoleService> consoleService;
8287 consoleService = mozilla::components::Console::Service();
8288 if (consoleService && !host.Equals(mapping->AlternateHost())) {
8289 nsAutoString message(u"Alternate Service Mapping found: "_ns);
8290 AppendASCIItoUTF16(scheme, message);
8291 message.AppendLiteral(u"://");
8292 AppendASCIItoUTF16(host, message);
8293 message.AppendLiteral(u":");
8294 message.AppendInt(port);
8295 message.AppendLiteral(u" to ");
8296 AppendASCIItoUTF16(scheme, message);
8297 message.AppendLiteral(u"://");
8298 AppendASCIItoUTF16(mapping->AlternateHost(), message);
8299 message.AppendLiteral(u":");
8300 message.AppendInt(mapping->AlternatePort());
8301 consoleService->LogStringMessage(message.get());
8302 }
8303
8304 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)
;
8305 mapping->GetConnectionInfo(getter_AddRefs(mConnectionInfo), proxyInfo,
8306 originAttributes);
8307 glean::http::transaction_use_altsvc
8308 .EnumGet(glean::http::TransactionUseAltsvcLabel::eTrue)
8309 .Add();
8310 if (mConnectionInfo->IsHttp3() &&
8311 StaticPrefs::
8312 network_http_http3_force_use_alt_svc_mapping_for_testing()) {
8313 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
8314 }
8315 } else if (mConnectionInfo) {
8316 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)
;
8317 glean::http::transaction_use_altsvc
8318 .EnumGet(glean::http::TransactionUseAltsvcLabel::eFalse)
8319 .Add();
8320 } else {
8321 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)
;
8322
8323 mConnectionInfo = connInfo;
8324 glean::http::transaction_use_altsvc
8325 .EnumGet(glean::http::TransactionUseAltsvcLabel::eFalse)
8326 .Add();
8327 }
8328
8329 bool trrEnabled = false;
8330 auto dnsStrategy = ComputeProxyDNSStrategy();
8331 bool httpsRRAllowed =
8332 !LoadBeConservative() && !(mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) &&
8333 !(mLoadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
8334 mLoadInfo->GetExternalContentPolicyType() !=
8335 ExtContentPolicy::TYPE_DOCUMENT) &&
8336 dnsStrategy == nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN &&
8337 !mConnectionInfo->UsingConnect() && canUseHTTPSRRonNetwork(trrEnabled) &&
8338 StaticPrefs::network_dns_use_https_rr_as_altsvc();
8339 if (!httpsRRAllowed) {
8340 DisallowHTTPSRR(mCaps);
8341 } else if (trrEnabled) {
8342 if (nsIRequest::GetTRRMode() != nsIRequest::TRR_DISABLED_MODE) {
8343 mCaps |= NS_HTTP_FORCE_WAIT_HTTP_RR(1 << 22);
8344 }
8345 }
8346
8347 auto canUseHappyEyeballs = [&]() {
8348 if (!StaticPrefs::network_http_happy_eyeballs_enabled()) {
8349 return false;
8350 }
8351
8352 if (LoadBeConservative() || (mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11))) {
8353 return false;
8354 }
8355
8356 if (mProxyInfo) {
8357 return false;
8358 }
8359
8360 // WebSocket and WebTransport upgrades share the same rollout pref.
8361 if ((mUpgradeProtocolCallback || mWebTransportSessionEventListener) &&
8362 !StaticPrefs::network_http_happy_eyeballs_upgrade_enabled()) {
8363 return false;
8364 }
8365
8366 // Connect-only requests need the extended-CONNECT tunnel path, which is
8367 // untested with Happy Eyeballs. These only reach us via a proxy today
8368 // (already excluded above), but guard explicitly against a future
8369 // non-proxied consumer.
8370 if (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) {
8371 return false;
8372 }
8373
8374 return true;
8375 };
8376
8377 if (canUseHappyEyeballs()) {
8378 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)
;
8379 mCaps |= NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30);
8380 mCaps &= ~NS_HTTP_FORCE_WAIT_HTTP_RR(1 << 22);
8381 mConnectionInfo =
8382 mConnectionInfo->Mutate().SetHappyEyeballsEnabled(true).Finalize();
8383 }
8384
8385 // No need to lookup HTTPSSVC record if mHTTPSSVCRecord already contains a
8386 // value.
8387 StoreUseHTTPSSVC(StaticPrefs::network_dns_upgrade_with_https_rr() &&
8388 httpsRRAllowed && mHTTPSSVCRecord.isNothing());
8389
8390 // Need to re-ask the handler, since mConnectionInfo may not be the connInfo
8391 // we used earlier
8392 if (!mConnectionInfo->IsHttp3() &&
8393 gHttpHandler->IsHttp2Excluded(mConnectionInfo)) {
8394 StoreAllowSpdy(0);
8395 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
8396 mConnectionInfo = mConnectionInfo->Mutate().SetNoSpdy(true).Finalize();
8397 }
8398
8399 // We can be passed with the auth provider if this channel was
8400 // a result of redirect due to auth retry
8401 if (!mAuthProvider) {
8402 mAuthProvider = new nsHttpChannelAuthProvider();
8403 }
8404
8405 rv = mAuthProvider->Init(this);
8406 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8407 return rv;
8408 }
8409
8410 // check to see if authorization headers should be included
8411 // CustomAuthHeader is set in AsyncOpen if we find Authorization header
8412 rv = mAuthProvider->AddAuthorizationHeaders(LoadCustomAuthHeader());
8413 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8414 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)
8415 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)
;
8416 }
8417
8418 // if this somehow fails we can go on without it
8419 (void)gHttpHandler->AddConnectionHeader(&mRequestHead, mCaps);
8420
8421 if (!LoadIsTRRServiceChannel() &&
8422 ((mLoadFlags & LOAD_FRESH_CONNECTION) ||
8423 (!StaticPrefs::network_dns_only_refresh_on_fresh_connection() &&
8424 (mLoadFlags & VALIDATE_ALWAYS ||
8425 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
)))) {
8426 mCaps |= NS_HTTP_REFRESH_DNS(1 << 3);
8427 }
8428
8429 if (gHttpHandler->CriticalRequestPrioritization()) {
8430 if (mClassOfService.Flags() & nsIClassOfService::Leader) {
8431 mCaps |= NS_HTTP_LOAD_AS_BLOCKING(1 << 6);
8432 }
8433 if (mClassOfService.Flags() & nsIClassOfService::Unblocked) {
8434 mCaps |= NS_HTTP_LOAD_UNBLOCKED(1 << 8);
8435 }
8436 if (mClassOfService.Flags() & nsIClassOfService::UrgentStart &&
8437 gHttpHandler->IsUrgentStartEnabled()) {
8438 mCaps |= NS_HTTP_URGENT_START(1 << 12);
8439 SetPriority(nsISupportsPriority::PRIORITY_HIGHEST);
8440 }
8441 }
8442
8443 // Force-Reload should reset the persistent connection pool.
8444 if (mLoadFlags & LOAD_FRESH_CONNECTION) {
8445 // Only the initial document resets the pool, and only for connections
8446 // sharing this channel's origin attributes.
8447 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
8448 gHttpHandler->AltServiceCache()->ClearAltServiceMappings();
8449 rv = gHttpHandler->DoShiftReloadConnectionCleanupWithConnInfo(
8450 mConnectionInfo);
8451 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8452 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)
8453 "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)
8454 "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)
8455 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)
;
8456 }
8457 }
8458 }
8459
8460 // We may have been cancelled already, either by on-modify-request
8461 // listeners or load group observers; in that case, we should not send the
8462 // request to the server
8463 if (mCanceled) {
8464 return mStatus;
8465 }
8466 // skip classifier checks if this channel was the result of internal auth
8467 // redirect
8468 bool shouldBeClassifiedForTracker =
8469 NS_ShouldClassifyChannel(this, ClassifyType::ETP);
8470
8471 if (shouldBeClassifiedForTracker) {
8472 if (LoadChannelClassifierCancellationPending()) {
8473 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)
8474 ("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)
8475 "[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)
8476 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
8477 return NS_OK;
8478 }
8479
8480 ReEvaluateReferrerAfterTrackingStatusIsKnown();
8481 }
8482
8483 MaybeStartDNSPrefetch();
8484
8485 // Update whether the channel is on the third-party cookie blocking exception
8486 // list.
8487 CookieService::Update3PCBExceptionInfo(this);
8488
8489 rv = CallOrWaitForResume(
8490 [](nsHttpChannel* self) { return self->PrepareToConnect(); });
8491 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8492 return rv;
8493 }
8494
8495 bool shouldBeClassifiedForSafeBrowsing =
8496 NS_ShouldClassifyChannel(this, ClassifyType::SafeBrowsing);
8497
8498 if (shouldBeClassifiedForTracker) {
8499 PrimeSuspendAfterExamineResponse();
8500 RefPtr<nsHttpChannel> self(this);
8501 nsresult rv =
8502 AntiTrackingChannelClassifierUtils::CheckChannelBeforeProcessResponse(
8503 this,
8504 [self]() { self->CancelSuspendOrResumeAfterExamineResponse(); });
8505 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8506 CancelSuspendOrResumeAfterExamineResponse();
8507 }
8508 }
8509
8510 if (shouldBeClassifiedForSafeBrowsing) {
8511 // Start nsChannelClassifier to catch phishing and malware URIs.
8512 RefPtr<nsChannelClassifier> channelClassifier =
8513 GetOrCreateChannelClassifier();
8514 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)
8515 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)
;
8516 channelClassifier->Start();
8517 }
8518
8519 return NS_OK;
8520}
8521
8522void nsHttpChannel::MaybeStartDNSPrefetch() {
8523 // Start a DNS lookup very early in case the real open is queued the DNS can
8524 // happen in parallel. Do not do so in the presence of an HTTP proxy as
8525 // all lookups other than for the proxy itself are done by the proxy.
8526 // Also we don't do a lookup if the LOAD_NO_NETWORK_IO or
8527 // LOAD_ONLY_FROM_CACHE flags are set.
8528 //
8529 // We keep the DNS prefetch object around so that we can retrieve
8530 // timing information from it. There is no guarantee that we actually
8531 // use the DNS prefetch data for the real connection, but as we keep
8532 // this data around for 3 minutes by default, this should almost always
8533 // be correct, and even when it isn't, the timing still represents _a_
8534 // valid DNS lookup timing for the site, even if it is not _the_
8535 // timing we used.
8536 if (mDNSPrefetch) {
8537 return;
8538 }
8539 if ((mLoadFlags & (LOAD_NO_NETWORK_IO | LOAD_ONLY_FROM_CACHE)) ||
8540 LoadAuthRedirectedChannel()) {
8541 return;
8542 }
8543
8544 auto dnsStrategy = ComputeProxyDNSStrategy();
8545
8546 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)
8547 ("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)
8548 "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)
8549 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)
8550 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)
;
8551
8552 if (dnsStrategy == nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN) {
8553 OriginAttributes originAttributes;
8554 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
8555 this, originAttributes);
8556
8557 mDNSPrefetch = new nsDNSPrefetch(mURI, originAttributes,
8558 nsIRequest::GetTRRMode(), this, true);
8559 nsIDNSService::DNSFlags dnsFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS;
8560 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
8561 dnsFlags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
8562 }
8563
8564 bool unused;
8565 if (StaticPrefs::network_dns_use_https_rr_as_altsvc() && !mHTTPSSVCRecord &&
8566 !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) &&
8567 canUseHTTPSRRonNetwork(unused)) {
8568 (void)mDNSPrefetch->FetchHTTPSSVC(mCaps & NS_HTTP_REFRESH_DNS(1 << 3), true,
8569 [](nsIDNSHTTPSSVCRecord*) {
8570 // Do nothing. This is a DNS prefetch.
8571 });
8572 }
8573
8574 if (StaticPrefs::network_http_happy_eyeballs_enabled()) {
8575 // Happy Eyeballs connects per-family, so issue per-family prefetches
8576 // (A and AAAA) that it can reuse instead of starting its own lookups.
8577 // Skip a family that won't be queried; with IPv6 disabled the AAAA
8578 // request collapses to A, so skip it to avoid a duplicate.
8579 bool skipIPv4 = mCaps & NS_HTTP_DISABLE_IPV4(1 << 17);
8580 bool skipIPv6 = (mCaps & NS_HTTP_DISABLE_IPV6(1 << 18)) ||
8581 StaticPrefs::network_dns_disableIPv6();
8582 (void)mDNSPrefetch->PrefetchHighPerFamily(dnsFlags, skipIPv4, skipIPv6);
8583 } else {
8584 if (mCaps & NS_HTTP_DISABLE_IPV4(1 << 17)) {
8585 dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4;
8586 } else if (mCaps & NS_HTTP_DISABLE_IPV6(1 << 18)) {
8587 dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6;
8588 }
8589 (void)mDNSPrefetch->PrefetchHigh(dnsFlags);
8590 }
8591 }
8592}
8593
8594bool nsHttpChannel::IsForcedOffline() const {
8595 RefPtr<mozilla::dom::BrowsingContext> bc;
8596 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
8597 if (!bc) {
8598 // Loads that are not performed by a window, such as keepalive fetches
8599 // handled by the FetchService and fetches from workers, only record the
8600 // browsing context they are associated with.
8601 mLoadInfo->GetAssociatedBrowsingContext(getter_AddRefs(bc));
8602 }
8603 return bc && bc->Top()->GetForceOffline();
8604}
8605
8606NS_IMETHODIMPnsresult
8607nsHttpChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) {
8608 if (mCacheEntry && !LoadCacheEntryIsWriteOnly()) {
8609 int64_t dataSize = 0;
8610 mCacheEntry->GetDataSize(&dataSize);
8611 *aEncodedBodySize = dataSize;
8612 } else {
8613 *aEncodedBodySize = mLogicalOffset;
8614 }
8615 return NS_OK;
8616}
8617
8618NS_IMETHODIMPnsresult
8619nsHttpChannel::GetDecompressDictionary(DictionaryCacheEntry** aDictionary) {
8620 *aDictionary = do_AddRef(mDictDecompress).take();
8621 return NS_OK;
8622}
8623
8624NS_IMETHODIMPnsresult
8625nsHttpChannel::SetDecompressDictionary(DictionaryCacheEntry* aDictionary) {
8626 if (!aDictionary) {
8627 if (mDictDecompress && mUsingDictionary) {
8628 mDictDecompress->UseCompleted();
8629 }
8630 mUsingDictionary = false;
8631 } else {
8632 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", 8632
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDictDecompress"
")"); do { MOZ_CrashSequence(__null, 8632); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8633 aDictionary->InUse();
8634 mUsingDictionary = true;
8635 }
8636 mDictDecompress = aDictionary;
8637 return NS_OK;
8638}
8639
8640//-----------------------------------------------------------------------------
8641// nsHttpChannel::nsIHttpChannelInternal
8642//-----------------------------------------------------------------------------
8643
8644NS_IMETHODIMPnsresult
8645nsHttpChannel::GetIsAuthChannel(bool* aIsAuthChannel) {
8646 *aIsAuthChannel = mIsAuthChannel;
8647 return NS_OK;
8648}
8649
8650NS_IMETHODIMPnsresult
8651nsHttpChannel::SetChannelIsForDownload(bool aChannelIsForDownload) {
8652 if (aChannelIsForDownload) {
8653 AddClassFlags(nsIClassOfService::Throttleable);
8654 } else {
8655 ClearClassFlags(nsIClassOfService::Throttleable);
8656 }
8657
8658 return HttpBaseChannel::SetChannelIsForDownload(aChannelIsForDownload);
8659}
8660
8661base::ProcessId nsHttpChannel::ProcessId() {
8662 nsCOMPtr<nsIParentChannel> parentChannel;
8663 NS_QueryNotificationCallbacks(this, parentChannel);
8664 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
8665 return httpParent->OtherPid();
8666 }
8667 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
8668 return docParent->OtherPid();
8669 }
8670 return base::GetCurrentProcId();
8671}
8672
8673auto nsHttpChannel::AttachStreamFilter() -> RefPtr<ChildEndpointPromise> {
8674 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)
;
8675 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", 8675
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 8675); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8676
8677 if (!ProcessId()) {
8678 return ChildEndpointPromise::CreateAndReject(false, __func__);
8679 }
8680
8681 nsCOMPtr<nsIParentChannel> parentChannel;
8682 NS_QueryNotificationCallbacks(this, parentChannel);
8683
8684 // If our listener is a DocumentLoadListener, then we might handle
8685 // multi-part responses here in the parent process. The current extension
8686 // API doesn't understand the parsed multipart format, so we defer responding
8687 // here until CallOnStartRequest, and attach the StreamFilter before the
8688 // multipart handler (in the parent process!) if applicable.
8689 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
8690 StreamFilterRequest* request = mStreamFilterRequests.AppendElement();
8691 request->mPromise = new ChildEndpointPromise::Private(__func__);
8692 return request->mPromise;
8693 }
8694
8695 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
8696 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
8697 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
8698 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8699 return ChildEndpointPromise::CreateAndReject(false, __func__);
8700 }
8701
8702 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
8703 return httpParent->AttachStreamFilter(std::move(parent), std::move(child));
8704 }
8705
8706 extensions::StreamFilterParent::Attach(this, std::move(parent));
8707 return ChildEndpointPromise::CreateAndResolve(std::move(child), __func__);
8708}
8709
8710NS_IMETHODIMPnsresult
8711nsHttpChannel::GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) {
8712 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)
;
8713 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"
, 8713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimeStamp"
")"); do { MOZ_CrashSequence(__null, 8713); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8714 *aTimeStamp = mNavigationStartTimeStamp;
8715 return NS_OK;
8716}
8717
8718NS_IMETHODIMPnsresult
8719nsHttpChannel::SetNavigationStartTimeStamp(TimeStamp aTimeStamp) {
8720 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)
;
8721 mNavigationStartTimeStamp = aTimeStamp;
8722 return NS_OK;
8723}
8724
8725//-----------------------------------------------------------------------------
8726// nsHttpChannel::nsISupportsPriority
8727//-----------------------------------------------------------------------------
8728
8729NS_IMETHODIMPnsresult
8730nsHttpChannel::SetPriority(int32_t value) {
8731 int16_t newValue = std::clamp<int32_t>(value, INT16_MIN(-32767-1), INT16_MAX(32767));
8732 if (mPriority == newValue) return NS_OK;
8733
8734 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)
;
8735
8736 mPriority = newValue;
8737 if (mTransaction) {
8738 nsresult rv = gHttpHandler->RescheduleTransaction(mTransaction, mPriority);
8739 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8740 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)
8741 ("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)
8742 "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)
8743 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)
;
8744 }
8745 }
8746
8747 // If this channel is the real channel for an e10s channel, notify the
8748 // child side about the priority change as well.
8749 nsCOMPtr<nsIParentChannel> parentChannel;
8750 NS_QueryNotificationCallbacks(this, parentChannel);
8751 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
8752 if (httpParent) {
8753 httpParent->DoSendSetPriority(newValue);
8754 }
8755
8756 return NS_OK;
8757}
8758
8759//-----------------------------------------------------------------------------
8760// HttpChannel::nsIClassOfService
8761//-----------------------------------------------------------------------------
8762
8763void nsHttpChannel::OnClassOfServiceUpdated() {
8764 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)
8765 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)
;
8766
8767 if (mTransaction) {
8768 gHttpHandler->UpdateClassOfServiceOnTransaction(mTransaction,
8769 mClassOfService);
8770 }
8771 if (EligibleForTailing()) {
8772 RemoveAsNonTailRequest();
8773 } else {
8774 AddAsNonTailRequest();
8775 }
8776}
8777
8778NS_IMETHODIMPnsresult
8779nsHttpChannel::SetClassFlags(uint32_t inFlags) {
8780 uint32_t previous = mClassOfService.Flags();
8781 mClassOfService.SetFlags(inFlags);
8782 if (previous != mClassOfService.Flags()) {
8783 OnClassOfServiceUpdated();
8784 }
8785 return NS_OK;
8786}
8787
8788NS_IMETHODIMPnsresult
8789nsHttpChannel::AddClassFlags(uint32_t inFlags) {
8790 uint32_t previous = mClassOfService.Flags();
8791 mClassOfService.SetFlags(inFlags | mClassOfService.Flags());
8792 if (previous != mClassOfService.Flags()) {
8793 OnClassOfServiceUpdated();
8794 }
8795 return NS_OK;
8796}
8797
8798NS_IMETHODIMPnsresult
8799nsHttpChannel::ClearClassFlags(uint32_t inFlags) {
8800 uint32_t previous = mClassOfService.Flags();
8801 mClassOfService.SetFlags(~inFlags & mClassOfService.Flags());
8802 if (previous != mClassOfService.Flags()) {
8803 OnClassOfServiceUpdated();
8804 }
8805 return NS_OK;
8806}
8807
8808NS_IMETHODIMPnsresult
8809nsHttpChannel::SetClassOfService(ClassOfService cos) {
8810 ClassOfService previous = mClassOfService;
8811 mClassOfService = cos;
8812 if (previous != mClassOfService) {
8813 OnClassOfServiceUpdated();
8814 }
8815 return NS_OK;
8816}
8817
8818NS_IMETHODIMPnsresult
8819nsHttpChannel::SetIncremental(bool incremental) {
8820 bool previous = mClassOfService.Incremental();
8821 mClassOfService.SetIncremental(incremental);
8822 if (previous != mClassOfService.Incremental()) {
8823 OnClassOfServiceUpdated();
8824 }
8825 return NS_OK;
8826}
8827
8828//-----------------------------------------------------------------------------
8829// nsHttpChannel::nsIProtocolProxyCallback
8830//-----------------------------------------------------------------------------
8831
8832NS_IMETHODIMPnsresult
8833nsHttpChannel::OnProxyAvailable(nsICancelable* request, nsIChannel* channel,
8834 nsIProxyInfo* pi, nsresult status) {
8835 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)
8836 " 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)
8837 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)
8838 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)
;
8839 mProxyRequest = nullptr;
8840
8841 nsresult rv;
8842
8843 // If status is a failure code, then it means that we failed to resolve
8844 // proxy info. That is a non-fatal error assuming it wasn't because the
8845 // request was canceled. We just failover to DIRECT when proxy resolution
8846 // fails (failure can mean that the PAC URL could not be loaded).
8847
8848 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
8849 mProxyInfo = pi;
8850
8851 if (mProxyInfo) {
8852 nsAutoCStringN<8> type;
8853 mProxyInfo->GetType(type);
8854 uint32_t flags = 0;
8855 mProxyInfo->GetFlags(&flags);
8856
8857 if (type.EqualsLiteral("socks")) {
8858 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
8859 glean::networking::proxy_info_type
8860 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5h)
8861 .Add(1);
8862 } else {
8863 glean::networking::proxy_info_type
8864 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5)
8865 .Add(1);
8866 }
8867 } else if (type.EqualsLiteral("socks4")) {
8868 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
8869 glean::networking::proxy_info_type
8870 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4a)
8871 .Add(1);
8872 } else {
8873 glean::networking::proxy_info_type
8874 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4)
8875 .Add(1);
8876 }
8877 } else if (type.EqualsLiteral("http")) {
8878 glean::networking::proxy_info_type
8879 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttp)
8880 .Add(1);
8881 } else if (type.EqualsLiteral("https")) {
8882 glean::networking::proxy_info_type
8883 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttps)
8884 .Add(1);
8885 } else if (type.EqualsLiteral("direct")) {
8886 glean::networking::proxy_info_type
8887 .EnumGet(glean::networking::ProxyInfoTypeLabel::eDirect)
8888 .Add(1);
8889 } else {
8890 glean::networking::proxy_info_type
8891 .EnumGet(glean::networking::ProxyInfoTypeLabel::eUnknown)
8892 .Add(1);
8893 }
8894 }
8895 }
8896
8897 if (!gHttpHandler->Active()) {
8898 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)
8899 ("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)
8900 "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)
8901 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
8902 rv = NS_ERROR_NOT_AVAILABLE;
8903 } else {
8904 rv = BeginConnect();
8905 }
8906
8907 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8908 CloseCacheEntry(false);
8909 (void)AsyncAbort(rv);
8910 }
8911 return rv;
8912}
8913
8914//-----------------------------------------------------------------------------
8915// nsHttpChannel::nsIProxiedChannel
8916//-----------------------------------------------------------------------------
8917
8918NS_IMETHODIMPnsresult
8919nsHttpChannel::GetProxyInfo(nsIProxyInfo** result) {
8920 if (!mConnectionInfo) {
8921 *result = do_AddRef(mProxyInfo).take();
8922 } else {
8923 *result = do_AddRef(mConnectionInfo->ProxyInfo()).take();
8924 }
8925 return NS_OK;
8926}
8927
8928//-----------------------------------------------------------------------------
8929// nsHttpChannel::nsITimedChannel
8930//-----------------------------------------------------------------------------
8931
8932NS_IMETHODIMPnsresult
8933nsHttpChannel::GetDomainLookupStart(TimeStamp* _retval) {
8934 if (mTransaction) {
8935 *_retval = mTransaction->GetDomainLookupStart();
8936 } else {
8937 *_retval = mTransactionTimings.domainLookupStart;
8938 }
8939 return NS_OK;
8940}
8941
8942NS_IMETHODIMPnsresult
8943nsHttpChannel::GetDomainLookupEnd(TimeStamp* _retval) {
8944 if (mTransaction) {
8945 *_retval = mTransaction->GetDomainLookupEnd();
8946 } else {
8947 *_retval = mTransactionTimings.domainLookupEnd;
8948 }
8949 return NS_OK;
8950}
8951
8952NS_IMETHODIMPnsresult
8953nsHttpChannel::GetConnectStart(TimeStamp* _retval) {
8954 if (mTransaction) {
8955 *_retval = mTransaction->GetConnectStart();
8956 } else {
8957 *_retval = mTransactionTimings.connectStart;
8958 }
8959 return NS_OK;
8960}
8961
8962NS_IMETHODIMPnsresult
8963nsHttpChannel::GetTcpConnectEnd(TimeStamp* _retval) {
8964 if (mTransaction) {
8965 *_retval = mTransaction->GetTcpConnectEnd();
8966 } else {
8967 *_retval = mTransactionTimings.tcpConnectEnd;
8968 }
8969 return NS_OK;
8970}
8971
8972NS_IMETHODIMPnsresult
8973nsHttpChannel::GetSecureConnectionStart(TimeStamp* _retval) {
8974 if (mTransaction) {
8975 *_retval = mTransaction->GetSecureConnectionStart();
8976 } else {
8977 *_retval = mTransactionTimings.secureConnectionStart;
8978 }
8979 return NS_OK;
8980}
8981
8982NS_IMETHODIMPnsresult
8983nsHttpChannel::GetConnectEnd(TimeStamp* _retval) {
8984 if (mTransaction) {
8985 *_retval = mTransaction->GetConnectEnd();
8986 } else {
8987 *_retval = mTransactionTimings.connectEnd;
8988 }
8989 return NS_OK;
8990}
8991
8992NS_IMETHODIMPnsresult
8993nsHttpChannel::GetRequestStart(TimeStamp* _retval) {
8994 if (mTransaction) {
8995 *_retval = mTransaction->GetRequestStart();
8996 } else {
8997 *_retval = mTransactionTimings.requestStart;
8998 }
8999 return NS_OK;
9000}
9001
9002NS_IMETHODIMPnsresult
9003nsHttpChannel::GetResponseStart(TimeStamp* _retval) {
9004 if (mTransaction) {
9005 *_retval = mTransaction->GetResponseStart();
9006 } else {
9007 *_retval = mTransactionTimings.responseStart;
9008 }
9009 return NS_OK;
9010}
9011
9012NS_IMETHODIMPnsresult
9013nsHttpChannel::GetFirstInterimResponseStart(TimeStamp* _retval) {
9014 if (mTransaction) {
9015 *_retval = mTransaction->GetFirstInterimResponseStart();
9016 } else {
9017 *_retval = mTransactionTimings.firstInterimResponseStart;
9018 }
9019 return NS_OK;
9020}
9021
9022NS_IMETHODIMPnsresult
9023nsHttpChannel::GetFinalResponseHeadersStart(TimeStamp* _retval) {
9024 if (mTransaction) {
9025 *_retval = mTransaction->GetFinalResponseHeadersStart();
9026 } else {
9027 *_retval = mTransactionTimings.finalResponseHeadersStart;
9028 }
9029 return NS_OK;
9030}
9031
9032NS_IMETHODIMPnsresult
9033nsHttpChannel::GetResponseEnd(TimeStamp* _retval) {
9034 if (mTransaction) {
9035 *_retval = mTransaction->GetResponseEnd();
9036 } else {
9037 *_retval = mTransactionTimings.responseEnd;
9038 }
9039 return NS_OK;
9040}
9041
9042NS_IMETHODIMPnsresult
9043nsHttpChannel::GetTransactionPending(TimeStamp* _retval) {
9044 if (mTransaction) {
9045 *_retval = mTransaction->GetPendingTime();
9046 } else {
9047 *_retval = mTransactionTimings.transactionPending;
9048 }
9049 return NS_OK;
9050}
9051
9052//-----------------------------------------------------------------------------
9053// nsHttpChannel::nsIHttpAuthenticableChannel
9054//-----------------------------------------------------------------------------
9055
9056NS_IMETHODIMPnsresult
9057nsHttpChannel::GetIsSSL(bool* aIsSSL) {
9058 // this attribute is really misnamed - it wants to know if
9059 // https:// is being used. SSL might be used to cover http://
9060 // in some circumstances (proxies, http/2, etc..)
9061 return mURI->SchemeIs("https", aIsSSL);
9062}
9063
9064NS_IMETHODIMPnsresult
9065nsHttpChannel::GetProxyMethodIsConnect(bool* aProxyMethodIsConnect) {
9066 *aProxyMethodIsConnect = mConnectionInfo->UsingConnect();
9067 return NS_OK;
9068}
9069
9070NS_IMETHODIMPnsresult
9071nsHttpChannel::GetServerResponseHeader(nsACString& value) {
9072 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
9073 return mResponseHead->GetHeader(nsHttp::Server, value);
9074}
9075
9076NS_IMETHODIMPnsresult
9077nsHttpChannel::GetProxyChallenges(nsACString& value) {
9078 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
9079 return mResponseHead->GetHeader(nsHttp::Proxy_Authenticate, value);
9080}
9081
9082NS_IMETHODIMPnsresult
9083nsHttpChannel::GetWWWChallenges(nsACString& value) {
9084 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
9085 return mResponseHead->GetHeader(nsHttp::WWW_Authenticate, value);
9086}
9087
9088NS_IMETHODIMPnsresult
9089nsHttpChannel::SetProxyCredentials(const nsACString& value) {
9090 return mRequestHead.SetHeader(nsHttp::Proxy_Authorization, value);
9091}
9092
9093NS_IMETHODIMPnsresult
9094nsHttpChannel::SetWWWCredentials(const nsACString& value) {
9095 // This method is called when various browser initiated authorization
9096 // code sets the credentials. We need to flag this header as the
9097 // "browser default" so it does not show up in the ServiceWorker
9098 // FetchEvent. This may actually get called more than once, though,
9099 // so we clear the header first since "default" headers are not
9100 // allowed to overwrite normally.
9101 (void)mRequestHead.ClearHeader(nsHttp::Authorization);
9102 return mRequestHead.SetHeader(nsHttp::Authorization, value, false,
9103 nsHttpHeaderArray::eVarietyRequestDefault);
9104}
9105
9106//-----------------------------------------------------------------------------
9107// Methods that nsIHttpAuthenticableChannel dupes from other IDLs, which we
9108// get from HttpBaseChannel, must be explicitly forwarded, because C++ sucks.
9109//-----------------------------------------------------------------------------
9110
9111NS_IMETHODIMPnsresult
9112nsHttpChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
9113 return HttpBaseChannel::GetLoadFlags(aLoadFlags);
9114}
9115
9116NS_IMETHODIMPnsresult
9117nsHttpChannel::GetURI(nsIURI** aURI) { return HttpBaseChannel::GetURI(aURI); }
9118
9119NS_IMETHODIMPnsresult
9120nsHttpChannel::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks) {
9121 return HttpBaseChannel::GetNotificationCallbacks(aCallbacks);
9122}
9123
9124NS_IMETHODIMPnsresult
9125nsHttpChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
9126 return HttpBaseChannel::GetLoadGroup(aLoadGroup);
9127}
9128
9129NS_IMETHODIMPnsresult
9130nsHttpChannel::GetRequestMethod(nsACString& aMethod) {
9131 return HttpBaseChannel::GetRequestMethod(aMethod);
9132}
9133
9134//-----------------------------------------------------------------------------
9135// nsHttpChannel::nsIRequestObserver
9136//-----------------------------------------------------------------------------
9137
9138void nsHttpChannel::RecordOnStartTelemetry(nsresult aStatus,
9139 bool aIsNavigation) {
9140 glean::http::channel_onstart_success
9141 .EnumGet(static_cast<glean::http::ChannelOnstartSuccessLabel>(
9142 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))))
9143 .Add();
9144
9145 mozilla::glean::networking::http_channel_onstart_status
9146 .Get(NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) ? "successful"_ns : "fail"_ns)
9147 .Add(1);
9148
9149 if (mTransaction) {
9150 glean::networking::http3_channel_onstart_success
9151 .Get((mTransaction->IsHttp3Used()) ? "http3"_ns : "no_http3"_ns,
9152 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) ? "true"_ns : "false"_ns)
9153 .Add();
9154 }
9155
9156 enum class HttpOnStartState : uint32_t {
9157 Success = 0,
9158 DNSError = 1,
9159 Others = 2,
9160 };
9161
9162 if (TRRService::Get() && TRRService::Get()->IsConfirmed()) {
9163 // Note this telemetry probe is not working when DNS resolution is done in
9164 // the socket process.
9165 HttpOnStartState state = HttpOnStartState::Others;
9166 if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
9167 state = HttpOnStartState::Success;
9168 } else if (aStatus == NS_ERROR_UNKNOWN_HOST ||
9169 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST) {
9170 state = HttpOnStartState::DNSError;
9171 }
9172
9173 if (aIsNavigation) {
9174 glean::http::channel_page_onstart_success_trr
9175 .Get(TRRService::ProviderKey())
9176 .AccumulateSingleSample(static_cast<uint32_t>(state));
9177 } else {
9178 glean::http::channel_sub_onstart_success_trr
9179 .Get(TRRService::ProviderKey())
9180 .AccumulateSingleSample(static_cast<uint32_t>(state));
9181 }
9182 }
9183
9184 if (nsIOService::UseSocketProcess() && mTransaction) {
9185 const TimeStamp now = TimeStamp::Now();
9186 TimeStamp responseEnd = mTransaction->GetResponseEnd();
9187 if (!responseEnd.IsNull()) {
9188 PerfStats::RecordMeasurement(PerfStats::Metric::ResponseEndSocketToParent,
9189 now - responseEnd);
9190 }
9191
9192 mOnStartRequestStartTime = mTransaction->GetOnStartRequestStartTime();
9193 if (!mOnStartRequestStartTime.IsNull()) {
9194 PerfStats::RecordMeasurement(
9195 PerfStats::Metric::OnStartRequestSocketToParent,
9196 now - mOnStartRequestStartTime);
9197 }
9198 } else {
9199 mOnStartRequestStartTime = TimeStamp::Now();
9200 }
9201}
9202
9203static bool hasConnectivity() {
9204 if (RefPtr<NetworkConnectivityService> ncs =
9205 NetworkConnectivityService::GetSingleton()) {
9206 nsINetworkConnectivityService::ConnectivityState state;
9207 if (NS_SUCCEEDED(ncs->GetIPv4(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetIPv4(&
state))), 1)))
&&
9208 state == nsINetworkConnectivityService::OK) {
9209 return true;
9210 }
9211 // We should also check for IPv6 connectivity here, but since
9212 // quite a few mozilla domains don't have IPv6 records yet,
9213 // we might incorrectly fallback to a backup domain on
9214 // IPv6 only networks.
9215 // When bug 1665605 gets fixed we can also return true when only IPv6 is OK.
9216 }
9217
9218 return false;
9219};
9220
9221static already_AddRefed<nsIURI> GetFallbackURI(nsIURI* aURI) {
9222 nsresult rv;
9223 nsAutoCString host;
9224 aURI->GetHost(host);
9225 nsCOMPtr<nsIURI> backupURI;
9226
9227 nsAutoCString fallbackDomain;
9228 if (!gIOService->GetFallbackDomain(host, fallbackDomain)) {
9229 return nullptr;
9230 }
9231
9232 rv = NS_MutateURI(aURI).SetHost(fallbackDomain).Finalize(backupURI);
9233 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9234 return nullptr;
9235 }
9236
9237 return backupURI.forget();
9238}
9239
9240// The essential domain fallback only targets Firefox's own internal requests
9241// Opening a link from browser UI or a priviledged page still carries the
9242// system principal so we need to exclude these regular pageloads.
9243static bool IsInternalSystemLoad(nsILoadInfo* aLoadInfo) {
9244 if (!aLoadInfo->TriggeringPrincipal()->IsSystemPrincipal()) {
9245 return false;
9246 }
9247
9248 ExtContentPolicyType type = aLoadInfo->GetExternalContentPolicyType();
9249 return type != ExtContentPolicy::TYPE_DOCUMENT &&
9250 type != ExtContentPolicy::TYPE_SUBDOCUMENT;
9251}
9252
9253// static
9254nsHttpChannel::EssentialDomainCategory
9255nsHttpChannel::GetEssentialDomainCategory(nsCString& domain) {
9256 if (StringEndsWith(domain, ".addons.mozilla.org"_ns)) {
9257 return EssentialDomainCategory::SubAddonsMozillaOrg;
9258 }
9259 if (domain == "addons.mozilla.org"_ns) {
9260 return EssentialDomainCategory::AddonsMozillaOrg;
9261 }
9262 if (domain == "aus5.mozilla.org"_ns) {
9263 return EssentialDomainCategory::Aus5MozillaOrg;
9264 }
9265 if (domain == "firefox.settings.services.mozilla.com"_ns ||
9266 domain == "firefox-settings-attachments.cdn.mozilla.net"_ns ||
9267 domain == "content-signature-2.cdn.mozilla.net"_ns) {
9268 return EssentialDomainCategory::RemoteSettings;
9269 }
9270 if (domain == "incoming.telemetry.mozilla.com"_ns) {
9271 return EssentialDomainCategory::Telemetry;
9272 }
9273 return EssentialDomainCategory::Other;
9274}
9275
9276// Helper function to send LNA access info to child process for console logging
9277// The child process has access to CallingScriptLocationString() which requires
9278// JS context
9279static void ReportLNAAccessToConsole(nsHttpChannel* aChannel,
9280 const char* aMessageName,
9281 const nsACString& aPromptAction = ""_ns) {
9282 // Send IPC to child process to log to console with script location
9283 nsCOMPtr<nsIParentChannel> parentChannel;
9284 NS_QueryNotificationCallbacks(aChannel, parentChannel);
9285 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
9286 NetAddr peerAddr = aChannel->GetPeerAddr();
9287
9288 // Fetch top-level site URI in parent process and pass via IPC.
9289 // We need to fetch this here because with Fission (site isolation),
9290 // cross-site iframes run in separate content processes and cannot
9291 // access the top-level document in a different process.
9292 nsAutoCString topLevelSite;
9293 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
9294 if (loadInfo) {
9295 RefPtr<mozilla::dom::BrowsingContext> bc;
9296 loadInfo->GetBrowsingContext(getter_AddRefs(bc));
9297 if (bc && bc->Top() && bc->Top()->Canonical()) {
9298 RefPtr<mozilla::dom::WindowGlobalParent> topWindowGlobal =
9299 bc->Top()->Canonical()->GetCurrentWindowGlobal();
9300 if (topWindowGlobal) {
9301 nsIPrincipal* topPrincipal = topWindowGlobal->DocumentPrincipal();
9302 if (topPrincipal) {
9303 nsCOMPtr<nsIURI> topURI = topPrincipal->GetURI();
9304 if (topURI) {
9305 (void)topURI->GetSpec(topLevelSite);
9306 }
9307 }
9308 }
9309 }
9310 }
9311
9312 httpParent->DoSendReportLNAToConsole(peerAddr, nsCString(aMessageName),
9313 nsCString(aPromptAction),
9314 topLevelSite);
9315 }
9316}
9317
9318nsresult nsHttpChannel::ProcessLNAActions() {
9319 if (!mTransaction) {
9320 return NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED;
9321 }
9322
9323 // Suspend to block any notification to the channel.
9324 // This will get resumed in
9325 // nsHttpChannel::OnPermissionPromptResult
9326 UpdateCurrentIpAddressSpace();
9327 mWaitingForLNAPermission = true;
9328 Suspend();
9329 auto targetAddressSpace = mTransaction->GetTargetIPAddressSpace();
9330 auto permissionKey = targetAddressSpace == nsILoadInfo::IPAddressSpace::Local
9331 ? LOOPBACK_NETWORK_PERMISSION_KEY
9332 : LOCAL_NETWORK_PERMISSION_KEY;
9333 LNAPermission permissionUpdateResult =
9334 UpdateLocalNetworkAccessPermissions(permissionKey);
9335
9336 if (LNAPermission::Granted == permissionUpdateResult) {
9337 // permission granted (auto-allow via permanent permission)
9338 mLNAPromptAction.AssignLiteral("auto_allow");
9339 return OnPermissionPromptResult(true, permissionKey);
9340 }
9341
9342 if (LNAPermission::Denied == permissionUpdateResult) {
9343 // permission denied (auto-deny via permanent permission)
9344 mLNAPromptAction.AssignLiteral("auto_deny");
9345 return OnPermissionPromptResult(false, permissionKey);
9346 }
9347
9348 // If we get here, we don't have any permission to access the local
9349 // host/network. We need to prompt the user for action
9350 auto permissionPromptCallback =
9351 [self = RefPtr{this}](bool aPermissionGranted, const nsACString& aType,
9352 bool aPromptShown) -> void {
9353 // Set mLNAPromptAction based on whether prompt was shown and user response
9354 if (aPromptShown) {
9355 if (aPermissionGranted) {
9356 self->mLNAPromptAction.AssignLiteral("prompt_allow");
9357 } else {
9358 self->mLNAPromptAction.AssignLiteral("prompt_deny");
9359 }
9360 } else {
9361 if (aPermissionGranted) {
9362 self->mLNAPromptAction.AssignLiteral("auto_allow");
9363 } else {
9364 self->mLNAPromptAction.AssignLiteral("auto_deny");
9365 }
9366 }
9367 self->OnPermissionPromptResult(aPermissionGranted, aType);
9368 };
9369
9370 RefPtr<LNAPermissionRequest> request = new LNAPermissionRequest(
9371 std::move(permissionPromptCallback), mLoadInfo, permissionKey);
9372
9373 // Log to console before requesting permission
9374 ReportLNAAccessToConsole(this, "LocalNetworkAccessPermissionRequired");
9375
9376 // This invokes callback nsHttpChannel::OnPermissionPromptResult
9377 // synchronously if the permission is already granted or denied
9378 // if permission is not available we prompt the user and in that case
9379 // nsHttpChannel::OnPermissionPromptResult is invoked asynchronously once
9380 // the user responds to the prompt
9381 return request->RequestPermission();
9382}
9383
9384void nsHttpChannel::UpdateCurrentIpAddressSpace() {
9385 if (!mTransaction) {
9386 return;
9387 }
9388
9389 if (mPeerAddr.GetIpAddressSpace() == nsILoadInfo::IPAddressSpace::Unknown) {
9390 // fetch peer address from transaction
9391 bool isTrr;
9392 bool echConfigUsed;
9393 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
9394 mEffectiveTRRMode, mTRRSkipReason,
9395 echConfigUsed);
9396 }
9397
9398 nsILoadInfo::IPAddressSpace docAddressSpace = mPeerAddr.GetIpAddressSpace();
9399 mLoadInfo->SetIpAddressSpace(docAddressSpace);
9400 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
9401 if (type == ExtContentPolicy::TYPE_DOCUMENT ||
9402 type == ExtContentPolicy::TYPE_SUBDOCUMENT) {
9403 RefPtr<mozilla::dom::BrowsingContext> bc;
9404 mLoadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
9405 if (bc) {
9406 bc->SetCurrentIPAddressSpace(docAddressSpace);
9407 }
9408
9409 if (mCacheEntry) {
9410 // store the ipaddr information into the cache metadata entry
9411 if (mPeerAddr.GetIpAddressSpace() !=
9412 nsILoadInfo::IPAddressSpace::Unknown) {
9413 uint16_t port;
9414 mPeerAddr.GetPort(&port);
9415 mCacheEntry->SetMetaDataElement("peer-ip-address",
9416 mPeerAddr.ToString().get());
9417 mCacheEntry->SetMetaDataElement("peer-port", ToString(port).c_str());
9418 }
9419 }
9420 }
9421}
9422
9423NS_IMETHODIMPnsresult
9424nsHttpChannel::OnStartRequest(nsIRequest* request) {
9425 nsresult rv;
9426
9427 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"
, 9427); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequestObserversCalled()"
")"); do { MOZ_CrashSequence(__null, 9427); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9428
9429 AUTO_PROFILER_LABEL("nsHttpChannel::OnStartRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject9429( "nsHttpChannel::OnStartRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
9430 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnStartRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject9431( "nsHttpChannel::OnStartRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
9431 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject9431( "nsHttpChannel::OnStartRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
9432
9433 if (!(mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))))) {
9434 // capture the request's status, so our consumers will know ASAP of any
9435 // connection failures, etc - bug 93581
9436 nsresult status;
9437 request->GetStatus(&status);
9438 mStatus = status;
9439 }
9440
9441 if (mStatus == NS_ERROR_NON_LOCAL_CONNECTION_REFUSED) {
9442 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"
, 9448, _profileOrCrashReason.get()); } while (false)
9443 "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"
, 9448, _profileOrCrashReason.get()); } while (false)
9444 "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"
, 9448, _profileOrCrashReason.get()); } while (false)
9445 "[%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"
, 9448, _profileOrCrashReason.get()); } while (false)
9446 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"
, 9448, _profileOrCrashReason.get()); } while (false)
9447 : "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"
, 9448, _profileOrCrashReason.get()); } while (false)
9448 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"
, 9448, _profileOrCrashReason.get()); } while (false)
;
9449 }
9450
9451 if (mStatus == NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED) {
9452 return ProcessLNAActions();
9453 }
9454
9455 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)
9456 "]\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)
9457 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)
;
9458
9459 RecordOnStartTelemetry(mStatus, IsNavigation());
9460
9461 // Make sure things are what we expect them to be...
9462 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"
, 9463); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { MOZ_CrashSequence(__null
, 9463); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
9463 "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"
, 9463); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { MOZ_CrashSequence(__null
, 9463); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9464
9465 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"
, 9469); 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, 9469); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9466 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"
, 9469); 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, 9469); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9467 "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"
, 9469); 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, 9469); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9468 "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"
, 9469); 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, 9469); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9469 "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"
, 9469); 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, 9469); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9470
9471 StoreAfterOnStartRequestBegun(true);
9472 if (mOnStartRequestTimestamp.IsNull()) {
9473 mOnStartRequestTimestamp = TimeStamp::Now();
9474 }
9475
9476 mozilla::glean::networking::http_onstart_suspend_total_time
9477 .AccumulateRawDuration(mSuspendTotalTime);
9478
9479 if (mTransaction) {
9480 mProxyConnectResponseHead = mTransaction->GetProxyConnectResponseHead();
9481 if (request == mTransactionPump) {
9482 StoreDataSentToChildProcess(mTransaction->DataSentToChildProcess());
9483 }
9484
9485 if (!mSecurityInfo && !mCachePump) {
9486 // grab the security info from the connection object; the transaction
9487 // is guaranteed to own a reference to the connection.
9488 mSecurityInfo = mTransaction->SecurityInfo();
9489 }
9490
9491 uint32_t stage = mTransaction->HTTPSSVCReceivedStage();
9492 if (!LoadHTTPSSVCTelemetryReported() && stage != HTTPSSVC_NOT_USED) {
9493 glean::http::dns_httpssvc_record_receiving_stage.AccumulateSingleSample(
9494 stage);
9495 }
9496
9497 if (HTTPS_RR_IS_USED(stage)(stage > HTTPSSVC_NOT_PRESENT && stage < HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_2
)
) {
9498 nsAutoCString suffix(LoadEchConfigUsed() ? "_ech_used" : "");
9499 // Determine the result string based on the status.
9500 nsAutoCString result(NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) ? "success" : "failure");
9501 result.Append(suffix);
9502
9503 mozilla::glean::networking::http_channel_onstart_success_https_rr
9504 .Get(result)
9505 .Add(1);
9506 StoreHasHTTPSRR(true);
9507 }
9508
9509 StoreLoadedBySocketProcess(mTransaction->AsHttpTransactionParent() !=
9510 nullptr);
9511
9512 bool isTrr;
9513 bool echConfigUsed;
9514 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
9515 mEffectiveTRRMode, mTRRSkipReason,
9516 echConfigUsed);
9517 // update IP AddressSpace for non-proxy connections and tests
9518 // We need to update the browsing context for tests as browser tests
9519 // uses local proxy to connect to
9520 // external domains
9521 if (!mProxyInfo || xpc::IsInAutomation()) {
9522 // If this is main document load or iframe store the IP Address space in
9523 // the browsing context
9524 UpdateCurrentIpAddressSpace();
9525 }
9526
9527 StoreResolvedByTRR(isTrr);
9528 StoreEchConfigUsed(echConfigUsed);
9529 } else { // !mTransaction
9530 MaybeUpdateDocumentIPAddressSpaceFromCache();
9531 }
9532
9533 if (!mCanceled && mTransaction && IsInternalSystemLoad(mLoadInfo)) {
9534 // We have to report telemetry before we actually attempt to redirect to
9535 // the fallback domain because doing so will change mStatus
9536 ReportSystemChannelTelemetry(mStatus);
9537 }
9538
9539 // don't enter this block if we're reading from the cache...
9540 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mCachePump && mTransaction) {
9541 // mTransactionPump doesn't hit OnInputStreamReady and call this until
9542 // all of the response headers have been acquired, so we can take
9543 // ownership of them from the transaction.
9544 RefPtr<nsHttpConnectionInfo> connInfo;
9545 mResponseHead =
9546 mTransaction->TakeResponseHeadAndConnInfo(getter_AddRefs(connInfo));
9547 mSupportsHTTP3 = mTransaction->GetSupportsHTTP3();
9548 // the response head may be null if the transaction was cancelled. in
9549 // which case we just need to call OnStartRequest/OnStopRequest.
9550 if (mResponseHead) {
9551 if (AntiTrackingUtils::ProcessStorageAccessHeadersShouldRetry(this)) {
9552 // force reload. Doom cache to avoid redirect loop
9553 if (mCacheEntry) {
9554 mCacheEntry->AsyncDoom(nullptr);
9555 }
9556
9557 auto storeAllowStorageAccess = [&](nsIChannel* aRedirectedChannel) {
9558 RefPtr<nsHttpChannel> httpChan = do_QueryObject(aRedirectedChannel);
9559 if (httpChan) {
9560 httpChan->StoreStorageAccessReloadChannel(true);
9561 }
9562 };
9563
9564 rv = StartRedirectChannelToURI(mURI,
9565 nsIChannelEventSink::REDIRECT_INTERNAL,
9566 storeAllowStorageAccess);
9567 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9568 Cancel(rv);
9569 return CallOnStartRequest();
9570 }
9571 return NS_OK;
9572 }
9573 return ProcessResponse(connInfo);
9574 }
9575
9576 NS_WARNING("No response head in OnStartRequest")NS_DebugBreak(NS_DEBUG_WARNING, "No response head in OnStartRequest"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9576)
;
9577 }
9578
9579 // cache file could be deleted on our behalf, it could contain errors or
9580 // it failed to allocate memory, reload from network here.
9581 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)
) {
9582 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)
;
9583 mCacheEntry->AsyncDoom(nullptr);
9584 rv =
9585 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
9586 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) return NS_OK;
9587 }
9588
9589 // If this is a system principal request to an essential domain and we
9590 // currently have connectivity, then check if there's a fallback domain we
9591 // can use to retry. If so we redirect to the fallback domain.
9592 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) && !mCanceled && IsInternalSystemLoad(mLoadInfo)) {
9593 if (StaticPrefs::network_essential_domains_fallback() &&
9594 hasConnectivity()) {
9595 auto passDomainCategory = [&](nsIChannel* aRedirectedChannel) {
9596 RefPtr<nsHttpChannel> httpChan = do_QueryObject(aRedirectedChannel);
9597 if (httpChan) {
9598 nsAutoCString host;
9599 mURI->GetHost(host);
9600 httpChan->mEssentialDomainCategory =
9601 Some(GetEssentialDomainCategory(host));
9602 }
9603 };
9604
9605 if (nsCOMPtr<nsIURI> fallbackURI = GetFallbackURI(mURI)) {
9606 rv = StartRedirectChannelToURI(fallbackURI,
9607 nsIChannelEventSink::REDIRECT_INTERNAL,
9608 passDomainCategory);
9609 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9610 nsCOMPtr<nsIObserverService> obsService =
9611 services::GetObserverService();
9612 if (obsService)
9613 obsService->NotifyObservers(static_cast<nsIHttpChannel*>(this),
9614 "httpchannel-fallback", nullptr);
9615 return NS_OK;
9616 }
9617 }
9618 }
9619 }
9620
9621 // avoid crashing if mListener happens to be null...
9622 if (!mListener) {
9623 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"
, 9623); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "mListener is null" ")"); do { MOZ_CrashSequence
(__null, 9623); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9624 return NS_OK;
9625 }
9626
9627 rv = ProcessCrossOriginSecurityHeaders();
9628 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9629 mStatus = rv;
9630 HandleAsyncAbort();
9631 return rv;
9632 }
9633
9634 // No process change is needed, so continue on to ContinueOnStartRequest1.
9635 return ContinueOnStartRequest1(rv);
9636}
9637
9638void nsHttpChannel::MaybeUpdateDocumentIPAddressSpaceFromCache() {
9639 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"
, 9639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 9639); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9640 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
9641
9642 // Update the IPAddressSpace in the BrowsingContext only for main or sub
9643 // document
9644 if (type != ExtContentPolicy::TYPE_DOCUMENT &&
9645 type != ExtContentPolicy::TYPE_SUBDOCUMENT) {
9646 return;
9647 }
9648
9649 RefPtr<mozilla::dom::BrowsingContext> bc;
9650 mLoadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
9651
9652 if (!bc || !mCacheEntry) {
9653 return;
9654 }
9655
9656 nsAutoCString ipAddrStr, portStr;
9657 mCacheEntry->GetMetaDataElement("peer-ip-address", getter_Copies(ipAddrStr));
9658 mCacheEntry->GetMetaDataElement("peer-port", getter_Copies(portStr));
9659
9660 nsresult rv;
9661 uint32_t port = portStr.ToInteger(&rv);
9662
9663 if (!ipAddrStr.IsEmpty() && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9664 NetAddr ipAddr;
9665 rv = ipAddr.InitFromString(ipAddrStr, port);
9666 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"
, 9666); return; } } while (false)
;
9667 mLoadInfo->SetIpAddressSpace(ipAddr.GetIpAddressSpace());
9668 bc->SetCurrentIPAddressSpace(ipAddr.GetIpAddressSpace());
9669 }
9670}
9671
9672nsresult nsHttpChannel::OnPermissionPromptResult(bool aGranted,
9673 const nsACString& aType) {
9674 mWaitingForLNAPermission = false;
9675
9676 if (aGranted) {
9677 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)
9678 ("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)
9679 "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)
9680 "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)
9681 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
9682 // we need to cache this data as permission manager is updated async and
9683 // might not be reflected immediately
9684 if (aType == LOOPBACK_NETWORK_PERMISSION_KEY) {
9685 mLNAPermission.mLocalHostPermission = LNAPermission::Granted;
9686 }
9687
9688 if (aType == LOCAL_NETWORK_PERMISSION_KEY) {
9689 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
9690 }
9691 // reset the transaction
9692 mTransaction = nullptr;
9693
9694 // resets streams and listener. Ensures we dont get any more callbacks to
9695 // nsHttpChannel from the pumps
9696 RefPtr<nsInputStreamPump> pump = do_QueryObject(mTransactionPump);
9697 if (pump) {
9698 pump->Reset();
9699 }
9700 mTransactionPump = nullptr;
9701
9702 // reset the status as we are going to replay the transaction
9703 mStatus = nsresult::NS_OK;
9704
9705 // allow notifications for the channel
9706 Resume();
9707 // replay the transaction with permisions granted
9708 return CallOrWaitForResume(
9709 [](auto* self) -> nsresult { return self->DoConnect(nullptr); });
9710 }
9711
9712 // permission denied
9713 // resume the transaction pump, we should get the OnStopRequest Notification
9714 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)
9715 ("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)
9716 "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)
9717 "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)
9718 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
9719
9720 Resume();
9721
9722 if (aType == LOOPBACK_NETWORK_PERMISSION_KEY) {
9723 mLNAPermission.mLocalHostPermission = LNAPermission::Denied;
9724 }
9725
9726 if (aType == LOCAL_NETWORK_PERMISSION_KEY) {
9727 mLNAPermission.mLocalNetworkPermission = LNAPermission::Denied;
9728 }
9729
9730 if (!mSuspendCount) {
9731 return ContinueOnStartRequest1(
9732 nsresult::NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED);
9733 }
9734 // channel is suspended state. We will continue when the channel is
9735 // resumed
9736 return CallOrWaitForResume([](auto* self) {
9737 return self->ContinueOnStartRequest1(
9738 nsresult::NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED);
9739 });
9740}
9741
9742nsresult nsHttpChannel::ContinueOnStartRequest1(nsresult result) {
9743 nsresult rv;
9744
9745 // if process selection failed, cancel this load.
9746 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
9747 Cancel(result);
9748 return CallOnStartRequest();
9749 }
9750
9751 // before we start any content load, check for redirectTo being called
9752 // this code is executed mainly before we start load from the cache
9753 if (mAPIRedirectTo && !mCanceled) {
9754 nsAutoCString redirectToSpec;
9755 mAPIRedirectTo->first()->GetAsciiSpec(redirectToSpec);
9756 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)
;
9757
9758 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", 9758
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 9758); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9759 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
9760 rv = StartRedirectChannelToURI(
9761 mAPIRedirectTo->first(),
9762 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_TEMPORARY |
9763 nsIChannelEventSink::REDIRECT_TRANSPARENT
9764 : nsIChannelEventSink::REDIRECT_TEMPORARY);
9765 mAPIRedirectTo = Nothing();
9766 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9767 return NS_OK;
9768 }
9769 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
9770 }
9771
9772 // Hack: ContinueOnStartRequest2 uses NS_OK to detect successful redirects,
9773 // so we distinguish this codepath (a non-redirect that's processing
9774 // normally) by passing in a bogus error code.
9775 return ContinueOnStartRequest2(NS_BINDING_FAILED);
9776}
9777
9778nsresult nsHttpChannel::ContinueOnStartRequest2(nsresult result) {
9779 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
9780 // Redirect has passed through, we don't want to go on with this
9781 // channel. It will now be canceled by the redirect handling code
9782 // that called this function.
9783 return NS_OK;
9784 }
9785
9786 // on proxy errors, try to failover
9787 if (mConnectionInfo->ProxyInfo() &&
9788 (mStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
9789 mStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
9790 mStatus == NS_ERROR_NET_TIMEOUT || mStatus == NS_ERROR_NET_RESET)) {
9791 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
9792 if (NS_SUCCEEDED(ProxyFailover())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ProxyFailover()))
, 1)))
) {
9793 mProxyConnectResponseHead = nullptr;
9794 return NS_OK;
9795 }
9796 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
9797 }
9798
9799 // Hack: ContinueOnStartRequest3 uses NS_OK to detect successful redirects,
9800 // so we distinguish this codepath (a non-redirect that's processing
9801 // normally) by passing in a bogus error code.
9802 return ContinueOnStartRequest3(NS_BINDING_FAILED);
9803}
9804
9805nsresult nsHttpChannel::ContinueOnStartRequest3(nsresult result) {
9806 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
9807 // Redirect has passed through, we don't want to go on with this
9808 // channel. It will now be canceled by the redirect handling code
9809 // that called this function.
9810 return NS_OK;
9811 }
9812
9813 return CallOnStartRequest();
9814}
9815
9816static void ReportHTTPSRRTelemetry(
9817 const Maybe<nsCOMPtr<nsIDNSHTTPSSVCRecord>>& aMaybeRecord) {
9818 bool hasHTTPSRR = aMaybeRecord && (aMaybeRecord.ref() != nullptr);
9819 if (!hasHTTPSRR) {
9820 mozilla::glean::networking::https_rr_presented.Get("none"_ns).Add(1);
9821 return;
9822 }
9823
9824 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& record = aMaybeRecord.ref();
9825 nsCOMPtr<nsISVCBRecord> svcbRecord;
9826 if (NS_SUCCEEDED(record->GetServiceModeRecord(false, false,((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
9827 getter_AddRefs(svcbRecord)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
) {
9828 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"
, 9828); AnnotateMozCrashReason("MOZ_ASSERT" "(" "svcbRecord"
")"); do { MOZ_CrashSequence(__null, 9828); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9829
9830 Maybe<std::tuple<nsCString, SupportedAlpnRank>> alpn =
9831 svcbRecord->GetAlpn();
9832 bool isHttp3 = alpn ? IsHttp3(std::get<1>(*alpn)) : false;
9833 mozilla::glean::networking::https_rr_presented
9834 .Get(isHttp3 ? "presented_with_http3"_ns : "presented"_ns)
9835 .Add(1);
9836 }
9837}
9838
9839static void RecordHttpChanDispositionGlean(ChannelDisposition chanDisposition) {
9840 switch (chanDisposition) {
9841 case kHttpCanceled:
9842 mozilla::glean::networking::http_channel_disposition
9843 .Get("http_cancelled"_ns)
9844 .Add(1);
9845 break;
9846 case kHttpDisk:
9847 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
9848 .Add(1);
9849 break;
9850 case kHttpNetOK:
9851 mozilla::glean::networking::http_channel_disposition.Get("http_net_ok"_ns)
9852 .Add(1);
9853 break;
9854 case kHttpNetEarlyFail:
9855 mozilla::glean::networking::http_channel_disposition
9856 .Get("http_net_early_fail"_ns)
9857 .Add(1);
9858 break;
9859 case kHttpNetLateFail:
9860 mozilla::glean::networking::http_channel_disposition
9861 .Get("http_net_late_fail"_ns)
9862 .Add(1);
9863 break;
9864 case kHttpsCanceled:
9865 mozilla::glean::networking::http_channel_disposition
9866 .Get("https_cancelled"_ns)
9867 .Add(1);
9868 break;
9869 case kHttpsDisk:
9870 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
9871 .Add(1);
9872 break;
9873 case kHttpsNetOK:
9874 mozilla::glean::networking::http_channel_disposition
9875 .Get("https_net_ok"_ns)
9876 .Add(1);
9877 break;
9878 case kHttpsNetEarlyFail:
9879 mozilla::glean::networking::http_channel_disposition
9880 .Get("https_net_early_fail"_ns)
9881 .Add(1);
9882 break;
9883 case kHttpsNetLateFail:
9884 mozilla::glean::networking::http_channel_disposition
9885 .Get("https_net_late_fail"_ns)
9886 .Add(1);
9887 break;
9888 default:
9889 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"
, 9889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for chanDisposition"
")"); do { MOZ_CrashSequence(__null, 9889); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9890 }
9891}
9892
9893enum class HttpChannelDispositionUpgrade {
9894 cancel,
9895 disk,
9896 netOk,
9897 netEarlyFail,
9898 netLateFail,
9899};
9900
9901static nsLiteralCString HttpChanDispositionToTelemetryLabel(
9902 HttpChannelDispositionUpgrade upgradeChanDisposition) {
9903 switch (upgradeChanDisposition) {
9904 case HttpChannelDispositionUpgrade::cancel:
9905 return "cancel"_ns;
9906 case HttpChannelDispositionUpgrade::disk:
9907 return "disk"_ns;
9908 case HttpChannelDispositionUpgrade::netOk:
9909 return "net_ok"_ns;
9910 case HttpChannelDispositionUpgrade::netEarlyFail:
9911 return "net_early_fail"_ns;
9912 case HttpChannelDispositionUpgrade::netLateFail:
9913 return "net_late_fail"_ns;
9914 }
9915
9916 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"
, 9916); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for upgradeChanDecomposition"
")"); do { MOZ_CrashSequence(__null, 9916); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9917 return "other"_ns;
9918}
9919
9920nsresult nsHttpChannel::LogConsoleError(const char* aTag) {
9921 nsCOMPtr<nsIConsoleService> console(mozilla::components::Console::Service());
9922 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", 9922
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9923
9924 nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
9925 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", 9925
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9926 uint64_t innerWindowID = loadInfo->GetInnerWindowID();
9927
9928 nsAutoString errorText;
9929 nsresult rv = nsContentUtils::GetLocalizedString(
9930 PropertiesFile::NECKO_PROPERTIES, aTag, errorText);
9931 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"
, 9931); return rv; } } while (false)
;
9932
9933 nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1"));
9934 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", 9934
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9935
9936 rv =
9937 error->InitWithSourceURI(errorText, mURI, 0, 0, nsIScriptError::errorFlag,
9938 "Invalid HTTP Status Lines"_ns, innerWindowID);
9939 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"
, 9939); return rv; } } while (false)
;
9940 console->LogMessage(error);
9941 return NS_OK;
9942}
9943
9944static void RecordHTTPSUpgradeTelemetry(nsIURI* aURI, nsILoadInfo* aLoadInfo) {
9945 // we record https telemetry only for top-level loads
9946 if (aLoadInfo->GetExternalContentPolicyType() !=
9947 ExtContentPolicy::TYPE_DOCUMENT) {
9948 return;
9949 }
9950
9951 // exempt loopback addresses because we only want to record telemetry
9952 // for actual web requests
9953 if (nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI)) {
9954 return;
9955 }
9956
9957 // todo: for now we don't record form submissions, only
9958 // top-level document loads. Once Bug 1720500 is fixed, we can
9959 // consider recording form submissions too.
9960 if (aLoadInfo->GetIsFormSubmission()) {
9961 return;
9962 }
9963
9964 bool isHTTPS = aURI->SchemeIs("https");
9965
9966 nsILoadInfo::HTTPSUpgradeTelemetryType httpsTelemetry =
9967 aLoadInfo->GetHttpsUpgradeTelemetry();
9968 switch (httpsTelemetry) {
9969 case nsILoadInfo::NOT_INITIALIZED: {
9970 if (isHTTPS) {
9971 // Bug 1912222: We should never encounter NOT_INITIALIZED values,
9972 // though we still want to know whether those loads are HTTPS
9973 // or not. Eventually we'll want to remove this if-clause
9974 // again and only report "not_initialized".
9975 mozilla::glean::networking::http_to_https_upgrade_reason
9976 .Get("not_initialized_https"_ns)
9977 .Add(1);
9978 return;
9979 }
9980 mozilla::glean::networking::http_to_https_upgrade_reason
9981 .Get("not_initialized"_ns)
9982 .Add(1);
9983 break;
9984 }
9985 case nsILoadInfo::NO_UPGRADE: {
9986 if (isHTTPS) {
9987 // Bug 1912222: We should rearely encounter NO_UPGRADE values, though
9988 // we still want to ensure those are not HTTPS. Eventually we'll want
9989 // to remove this if-clause again and only report "no_upgrade".
9990 mozilla::glean::networking::http_to_https_upgrade_reason
9991 .Get("no_upgrade_https"_ns)
9992 .Add(1);
9993 return;
9994 }
9995 mozilla::glean::networking::http_to_https_upgrade_reason
9996 .Get("no_upgrade"_ns)
9997 .Add(1);
9998 break;
9999 }
10000 case nsILoadInfo::ALREADY_HTTPS:
10001 mozilla::glean::networking::http_to_https_upgrade_reason
10002 .Get("already_https"_ns)
10003 .Add(1);
10004 break;
10005 case nsILoadInfo::HSTS:
10006 mozilla::glean::networking::http_to_https_upgrade_reason.Get("hsts"_ns)
10007 .Add(1);
10008 break;
10009 case nsILoadInfo::HTTPS_ONLY_UPGRADE:
10010 mozilla::glean::networking::http_to_https_upgrade_reason
10011 .Get("https_only_upgrade"_ns)
10012 .Add(1);
10013 break;
10014 case nsILoadInfo::HTTPS_ONLY_UPGRADE_DOWNGRADE:
10015 mozilla::glean::networking::http_to_https_upgrade_reason
10016 .Get("https_only_upgrade_downgrade"_ns)
10017 .Add(1);
10018 break;
10019 case nsILoadInfo::HTTPS_FIRST_UPGRADE:
10020 mozilla::glean::networking::http_to_https_upgrade_reason
10021 .Get("https_first_upgrade"_ns)
10022 .Add(1);
10023 break;
10024 case nsILoadInfo::HTTPS_FIRST_UPGRADE_DOWNGRADE:
10025 mozilla::glean::networking::http_to_https_upgrade_reason
10026 .Get("https_first_upgrade_downgrade"_ns)
10027 .Add(1);
10028 break;
10029 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE:
10030 mozilla::glean::networking::http_to_https_upgrade_reason
10031 .Get("https_first_schemeless_upgrade"_ns)
10032 .Add(1);
10033 break;
10034 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE_DOWNGRADE:
10035 mozilla::glean::networking::http_to_https_upgrade_reason
10036 .Get("https_first_schemeless_upgrade_downgrade"_ns)
10037 .Add(1);
10038 break;
10039 case nsILoadInfo::CSP_UIR:
10040 mozilla::glean::networking::http_to_https_upgrade_reason.Get("csp_uir"_ns)
10041 .Add(1);
10042 break;
10043 case nsILoadInfo::HTTPS_RR:
10044 mozilla::glean::networking::http_to_https_upgrade_reason
10045 .Get("https_rr"_ns)
10046 .Add(1);
10047 break;
10048 case nsILoadInfo::WEB_EXTENSION_UPGRADE:
10049 mozilla::glean::networking::http_to_https_upgrade_reason
10050 .Get("web_extension_upgrade"_ns)
10051 .Add(1);
10052 break;
10053 case nsILoadInfo::UPGRADE_EXCEPTION:
10054 mozilla::glean::networking::http_to_https_upgrade_reason
10055 .Get("upgrade_exception"_ns)
10056 .Add(1);
10057 break;
10058 case nsILoadInfo::SKIP_HTTPS_UPGRADE:
10059 mozilla::glean::networking::http_to_https_upgrade_reason
10060 .Get("skip_upgrade"_ns)
10061 .Add(1);
10062 break;
10063 default:
10064 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"
, 10064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"what telemetry flag is set to end up here?" ")"); do { MOZ_CrashSequence
(__null, 10064); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10065 }
10066}
10067
10068static void RecordIPAddressSpaceTelemetry(bool aLoadSuccess, nsIURI* aURI,
10069 nsILoadInfo* aLoadInfo,
10070 NetAddr& aPeerAddr) {
10071 // if the load was not successful, then there is nothing to record here
10072 if (!aLoadSuccess) {
10073 return;
10074 }
10075
10076 // we record https telemetry only for top-level loads
10077 if (aLoadInfo->GetExternalContentPolicyType() !=
10078 ExtContentPolicy::TYPE_DOCUMENT) {
10079 return;
10080 }
10081
10082 if (aURI->SchemeIs("https")) {
10083 mozilla::glean::networking::https_http_or_local.Get("load_is_https"_ns)
10084 .Add(1);
10085 return;
10086 }
10087
10088 if (aURI->SchemeIs("http")) {
10089 if (aPeerAddr.IsIPAddrLocal() || aPeerAddr.IsLoopbackAddr()) {
10090 mozilla::glean::networking::https_http_or_local
10091 .Get("load_is_http_for_local_domain"_ns)
10092 .Add(1);
10093 } else {
10094 mozilla::glean::networking::https_http_or_local.Get("load_is_http"_ns)
10095 .Add(1);
10096 }
10097 return;
10098 }
10099}
10100
10101static void RecordLNATelemetry(nsHttpChannel* aChannel, bool aLoadSuccess) {
10102 // Extract data from channel
10103 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
10104 nsCOMPtr<nsIURI> uri;
10105 aChannel->GetURI(getter_AddRefs(uri));
10106 NetAddr peerAddr = aChannel->GetPeerAddr();
10107 const nsACString& promptAction = aChannel->GetLNAPromptAction();
10108
10109 if (!loadInfo || !uri) {
10110 return;
10111 }
10112
10113 RefPtr<mozilla::dom::BrowsingContext> bc;
10114 loadInfo->GetBrowsingContext(getter_AddRefs(bc));
10115
10116 nsILoadInfo::IPAddressSpace parentAddressSpace =
10117 mozilla::net::GetParentIPAddressSpace(loadInfo);
10118
10119 // Early return if NOT LNA - don't record telemetry or log
10120 if (!mozilla::net::IsLocalOrPrivateNetworkAccess(
10121 parentAddressSpace, loadInfo->GetIpAddressSpace())) {
10122 return;
10123 }
10124
10125 if (aLoadSuccess) {
10126 mozilla::glean::networking::local_network_access.Get("success"_ns).Add(1);
10127 } else {
10128 mozilla::glean::networking::local_network_access.Get("failure"_ns).Add(1);
10129 }
10130
10131 uint16_t port = 0;
10132 peerAddr.GetPort(&port);
10133
10134 // label format is <parentAddressSpace>_to_<targetAddressSpace>_<scheme>
10135 // At this point we are sure that the request is a LNA,
10136 // Hence we can safely assume few conditions to construct the label
10137 nsAutoCString glean_lna_label;
10138 if (parentAddressSpace == nsILoadInfo::IPAddressSpace::Public) {
10139 glean_lna_label.Append("public_to_"_ns);
10140 } else {
10141 glean_lna_label.Append("private_to_"_ns);
10142 }
10143 if (loadInfo->GetIpAddressSpace() == nsILoadInfo::IPAddressSpace::Private) {
10144 glean_lna_label.Append("private_"_ns);
10145 } else {
10146 glean_lna_label.Append("local_"_ns);
10147 }
10148 if (uri->SchemeIs("https")) {
10149 glean_lna_label.Append("https"_ns);
10150 } else {
10151 glean_lna_label.Append("http"_ns);
10152 }
10153
10154 mozilla::glean::networking::local_network_access.Get(glean_lna_label).Add(1);
10155
10156 // Get top-level site (main window principal) - TLD+1
10157 nsAutoCString topLevelSite;
10158 if (bc && bc->Top()) {
10159 if (bc->Top()->Canonical()) {
10160 RefPtr<mozilla::dom::WindowGlobalParent> topWindowGlobal =
10161 bc->Top()->Canonical()->GetCurrentWindowGlobal();
10162 if (topWindowGlobal) {
10163 nsCOMPtr<nsIPrincipal> topPrincipal =
10164 topWindowGlobal->DocumentPrincipal();
10165 if (topPrincipal) {
10166 (void)topPrincipal->GetBaseDomain(topLevelSite);
10167 }
10168 }
10169 }
10170 }
10171
10172 // Get initiator (triggering principal) - TLD+1
10173 nsAutoCString initiator;
10174 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
10175 loadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
10176 if (triggeringPrincipal) {
10177 (void)triggeringPrincipal->GetBaseDomain(initiator);
10178 }
10179
10180 bool isSecureContext =
10181 triggeringPrincipal
10182 ? triggeringPrincipal->GetIsOriginPotentiallyTrustworthy()
10183 : false;
10184
10185 // Get target host - TLD+1
10186 nsCOMPtr<nsIEffectiveTLDService> eTLDService =
10187 mozilla::components::EffectiveTLD::Service();
10188 nsAutoCString targetHost;
10189 if (eTLDService) {
10190 (void)eTLDService->GetBaseDomain(uri, 0, targetHost);
10191 }
10192
10193 // Get target IP address
10194 nsCString targetIp = peerAddr.ToString();
10195
10196 // Determine protocol from LoadInfo
10197 nsAutoCString protocol;
10198 ExtContentPolicyType contentType = loadInfo->GetExternalContentPolicyType();
10199 switch (contentType) {
10200 case ExtContentPolicyType::TYPE_WEBSOCKET:
10201 protocol.AssignLiteral("websocket");
10202 break;
10203 case ExtContentPolicyType::TYPE_WEB_TRANSPORT:
10204 protocol.AssignLiteral("webtransport");
10205 break;
10206 case ExtContentPolicyType::TYPE_FETCH:
10207 protocol.AssignLiteral("fetch");
10208 break;
10209 case ExtContentPolicyType::TYPE_XMLHTTPREQUEST:
10210 protocol.AssignLiteral("xhr");
10211 break;
10212 default:
10213 if (uri->SchemeIs("https")) {
10214 protocol.AssignLiteral("https");
10215 } else {
10216 protocol.AssignLiteral("http");
10217 }
10218 break;
10219 }
10220
10221 // Record the event
10222 glean::networking::LocalNetworkAccessConnectionExtra extra = {
10223 .initiator = initiator.IsEmpty() ? Nothing() : Some(initiator),
10224 .isSecureContext = Some(isSecureContext),
10225 .loadSuccess = Some(aLoadSuccess),
10226 .promptAction =
10227 promptAction.IsEmpty() ? Nothing() : Some(nsCString(promptAction)),
10228 .protocol = Some(protocol),
10229 .targetHost = targetHost.IsEmpty() ? Nothing() : Some(targetHost),
10230 .targetIp = Some(targetIp),
10231 .targetPort = Some(port),
10232 .topLevelSite = topLevelSite.IsEmpty() ? Nothing() : Some(topLevelSite),
10233
10234 };
10235 glean::networking::local_network_access_connection.Record(Some(extra));
10236
10237 ReportLNAAccessToConsole(aChannel, "LocalNetworkAccessDetected",
10238 promptAction);
10239}
10240
10241NS_IMETHODIMPnsresult
10242nsHttpChannel::OnStopRequest(nsIRequest* request, nsresult status) {
10243 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", 10243
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncOpenTime.IsNull()"
")"); do { MOZ_CrashSequence(__null, 10243); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10244 AUTO_PROFILER_LABEL("nsHttpChannel::OnStopRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject10244( "nsHttpChannel::OnStopRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
10245 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnStopRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10246( "nsHttpChannel::OnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10246 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10246( "nsHttpChannel::OnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10247
10248 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)
10249 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)
;
10250
10251 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)
10252 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)
;
10253
10254 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"
, 10255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { MOZ_CrashSequence(__null, 10255); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10255 "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"
, 10255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { MOZ_CrashSequence(__null, 10255); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10256
10257 if (mStatus == NS_ERROR_PARSING_HTTP_STATUS_LINE) {
10258 (void)LogConsoleError("InvalidHTTPResponseStatusLine");
10259 }
10260
10261 // It's possible that LoadUseHTTPSSVC() is false, but we already have
10262 // mHTTPSSVCRecord.
10263 if (LoadUseHTTPSSVC() || mHTTPSSVCRecord) {
10264 ReportHTTPSRRTelemetry(mHTTPSSVCRecord);
10265 }
10266
10267 // If this load failed because of a security error, it may be because we
10268 // are in a captive portal - trigger an async check to make sure.
10269 int32_t nsprError = -1 * NS_ERROR_GET_CODE(status);
10270 if (mozilla::psm::IsNSSErrorCode(nsprError) && IsHTTPS()) {
10271 gIOService->RecheckCaptivePortal();
10272 }
10273
10274 if (request == mCachePump) {
10275 mCacheReadEnd = TimeStamp::Now();
10276 }
10277
10278 // allow content to be cached if it was loaded successfully (bug #482935)
10279 bool contentComplete = NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)));
10280
10281 // honor the cancelation status even if the underlying transaction
10282 // completed.
10283 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) status = mStatus;
10284
10285 if (LoadCachedContentIsPartial()) {
10286 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
10287 // mTransactionPump should be suspended
10288 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"
, 10289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ MOZ_CrashSequence(__null, 10289); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
10289 "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"
, 10289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ MOZ_CrashSequence(__null, 10289); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
10290
10291 if (request == mCachePump) {
10292 bool streamDone;
10293 status = OnDoneReadingPartialCacheEntry(&streamDone);
10294 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) && !streamDone) return status;
10295 // otherwise, fall through and fire OnStopRequest...
10296 } else if (request == mTransactionPump) {
10297 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", 10297
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { MOZ_CrashSequence(__null, 10297); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10298 } else {
10299 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"
, 10299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected request" ")"); do { MOZ_CrashSequence
(__null, 10299); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10300 }
10301 }
10302 // Do not to leave the transaction in a suspended state in error cases.
10303 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) && mTransaction) {
10304 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, status);
10305 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10306 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)
;
10307 }
10308 }
10309 }
10310
10311 nsCOMPtr<nsICompressConvStats> conv = do_QueryInterface(mCompressListener);
10312 if (conv) {
10313 uint64_t decodedDataLength = 0;
10314 conv->GetDecodedDataLength(&decodedDataLength);
10315 mDecodedBodySize = decodedDataLength;
10316 }
10317
10318 bool isFromNet = request == mTransactionPump;
10319
10320 if (mTransaction) {
10321 // determine if we should call DoAuthRetry
10322 bool authRetry = (mAuthRetryPending && NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) &&
10323 // we should only auth retry in this channel if are not
10324 // redirecting a new channel for authentication retries
10325 !StaticPrefs::network_auth_use_redirect_for_retries());
10326
10327 StoreStronglyFramed(mTransaction->ResponseIsComplete());
10328 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)
10329 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)
;
10330
10331 // Save the reference of |mTransaction| to |transactionWithStickyConn|
10332 // when it has a sticky connection.
10333 // In the case we need to retry an authentication request, we need to
10334 // reuse the connection of |transactionWithStickyConn|.
10335 RefPtr<HttpTransactionShell> transactionWithStickyConn;
10336 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
10337 mTransaction->HasStickyConnection()) {
10338 transactionWithStickyConn = mTransaction;
10339 // Make sure we use the updated caps and connection info from transaction.
10340 // We read these values when the transaction is already closed, so there
10341 // should be no race.
10342 if (mTransaction->Http2Disabled()) {
10343 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
10344 }
10345 if (mTransaction->Http3Disabled()) {
10346 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
10347 }
10348 mConnectionInfo = mTransaction->GetConnInfo();
10349 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)
10350 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)
;
10351 }
10352
10353 // this code relies on the code in nsHttpTransaction::Close, which
10354 // tests for NS_HTTP_STICKY_CONNECTION to determine whether or not to
10355 // keep the connection around after the transaction is finished.
10356 //
10357 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)
10358 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)
10359 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)
;
10360 // We must check caps for stickinness also on the transaction because it
10361 // might have been updated by the transaction itself during inspection of
10362 // the reposnse headers yet on the socket thread (found connection based
10363 // auth schema).
10364
10365 if ((NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) && transactionWithStickyConn) {
10366 // Close (don't reuse) the sticky connection if this channel has been
10367 // cancelled. There are proxy servers known to get confused when we send
10368 // a new request over such a half-stated connection.
10369 if (!LoadAuthConnectionRestartable()) {
10370 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)
;
10371 transactionWithStickyConn->DontReuseConnection();
10372 }
10373 }
10374
10375 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) {
10376 mTransaction->SetH2WSConnRefTaken();
10377 }
10378
10379 mTransferSize = mTransaction->GetTransferSize();
10380 mRequestSize = mTransaction->GetRequestSize();
10381
10382 RecordHTTPSUpgradeTelemetry(mURI, mLoadInfo);
10383
10384 RecordIPAddressSpaceTelemetry(NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))), mURI, mLoadInfo,
10385 mPeerAddr);
10386 RecordLNATelemetry(this, NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))));
10387
10388 uint32_t flags;
10389 if (mStatus == NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED &&
10390 StaticPrefs::network_lna_block_trackers() &&
10391 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
10392 mLoadInfo->GetTriggeringThirdPartyClassificationFlags(&flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
&&
10393 flags != 0) {
10394 mozilla::glean::networking::local_network_blocked_tracker.Add(1);
10395 }
10396
10397 // If we are using the transaction to serve content, we also save the
10398 // time since async open in the cache entry so we can compare telemetry
10399 // between cache and net response.
10400 // Do not store the time of conditional requests because even if we
10401 // fetch the data from the server, the time includes loading of the old
10402 // cache entry which would skew the network load time.
10403 if (request == mTransactionPump && mCacheEntry && !mDidReval &&
10404 !LoadCustomConditionalRequest() && !mAsyncOpenTime.IsNull() &&
10405 !mOnStartRequestTimestamp.IsNull()) {
10406 uint64_t onStartTime =
10407 (mOnStartRequestTimestamp - mAsyncOpenTime).ToMilliseconds();
10408 uint64_t onStopTime =
10409 (TimeStamp::Now() - mAsyncOpenTime).ToMilliseconds();
10410 (void)mCacheEntry->SetNetworkTimes(onStartTime, onStopTime);
10411 }
10412
10413 mResponseTrailers = mTransaction->TakeResponseTrailers();
10414
10415 if (nsIOService::UseSocketProcess() && mTransaction) {
10416 mOnStopRequestStartTime = mTransaction->GetOnStopRequestStartTime();
10417 if (!mOnStopRequestStartTime.IsNull()) {
10418 PerfStats::RecordMeasurement(
10419 PerfStats::Metric::OnStopRequestSocketToParent,
10420 TimeStamp::Now() - mOnStopRequestStartTime);
10421 }
10422 } else {
10423 mOnStopRequestStartTime = TimeStamp::Now();
10424 }
10425
10426 // at this point, we're done with the transaction
10427 mTransactionTimings = mTransaction->Timings();
10428 mTransaction = nullptr;
10429 mTransactionPump = nullptr;
10430
10431 // We no longer need the dns prefetch object
10432 if (mDNSPrefetch && mDNSPrefetch->TimingsValid() &&
10433 !mTransactionTimings.requestStart.IsNull() &&
10434 !mTransactionTimings.connectStart.IsNull() &&
10435 mDNSPrefetch->EndTimestamp() <= mTransactionTimings.connectStart) {
10436 // We only need the domainLookup timestamps when not using a
10437 // persistent connection, meaning if the endTimestamp < connectStart
10438 mTransactionTimings.domainLookupStart = mDNSPrefetch->StartTimestamp();
10439 mTransactionTimings.domainLookupEnd = mDNSPrefetch->EndTimestamp();
10440 }
10441 mDNSPrefetch = nullptr;
10442
10443 // handle auth retry...
10444 if (authRetry) {
10445 mAuthRetryPending = false;
10446 auto continueOSR = [authRetry, isFromNet, contentComplete,
10447 transactionWithStickyConn](auto* self,
10448 nsresult aStatus) {
10449 return self->ContinueOnStopRequestAfterAuthRetry(
10450 aStatus, authRetry, isFromNet, contentComplete,
10451 transactionWithStickyConn);
10452 };
10453 status = DoAuthRetry(transactionWithStickyConn, continueOSR);
10454 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
10455 return NS_OK;
10456 }
10457 }
10458 return ContinueOnStopRequestAfterAuthRetry(status, authRetry, isFromNet,
10459 contentComplete,
10460 transactionWithStickyConn);
10461 }
10462
10463 return ContinueOnStopRequest(status, isFromNet, contentComplete);
10464}
10465
10466nsresult nsHttpChannel::ContinueOnStopRequestAfterAuthRetry(
10467 nsresult aStatus, bool aAuthRetry, bool aIsFromNet, bool aContentComplete,
10468 HttpTransactionShell* aTransWithStickyConn) {
10469 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)
10470 ("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)
10471 "[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)
10472 " 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)
10473 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)
10474 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)
;
10475
10476 if (aAuthRetry && NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
10477 return NS_OK;
10478 }
10479
10480 // If DoAuthRetry failed, or if we have been cancelled since showing
10481 // the auth. dialog, then we need to send OnStartRequest now
10482 if (aAuthRetry || (mAuthRetryPending && NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0))))) {
10483 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"
, 10483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))"
") (" "should have a failure code here" ")"); do { MOZ_CrashSequence
(__null, 10483); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10484 // NOTE: since we have a failure status, we can ignore the return
10485 // value from onStartRequest.
10486 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)
10487 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)
;
10488 if (mListener) {
10489 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"
, 10490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10490); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10490 "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"
, 10490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10490); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10491 if (!LoadOnStartRequestCalled()) {
10492 nsCOMPtr<nsIStreamListener> listener(mListener);
10493 StoreOnStartRequestCalled(true);
10494 listener->OnStartRequest(this);
10495 }
10496 } else {
10497 StoreOnStartRequestCalled(true);
10498 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"
, 10498)
;
10499 }
10500 mAuthRetryPending = false;
10501 }
10502
10503 // if this transaction has been replaced, then bail.
10504 if (LoadTransactionReplaced()) {
10505 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)
;
10506 // This was just the network check for a 304 response.
10507 mFirstResponseSource = RESPONSE_PENDING;
10508 return NS_OK;
10509 }
10510
10511 bool upgradeWebsocket = mUpgradeProtocolCallback && aTransWithStickyConn &&
10512 mResponseHead &&
10513 ((mResponseHead->Status() == 101 &&
10514 mResponseHead->Version() == HttpVersion::v1_1) ||
10515 (mResponseHead->Status() == 200 &&
10516 mResponseHead->Version() == HttpVersion::v2_0));
10517
10518 bool upgradeConnect = mUpgradeProtocolCallback && aTransWithStickyConn &&
10519 (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) && mResponseHead &&
10520 mResponseHead->Status() == 200;
10521
10522 if (upgradeWebsocket || upgradeConnect) {
10523 if (nsIOService::UseSocketProcess() && upgradeConnect) {
10524 // TODO: Support connection upgrade for socket process in bug 1632809.
10525 (void)mUpgradeProtocolCallback->OnUpgradeFailed(NS_ERROR_NOT_IMPLEMENTED);
10526 return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
10527 }
10528
10529 nsresult rv = gHttpHandler->CompleteUpgrade(aTransWithStickyConn,
10530 mUpgradeProtocolCallback);
10531 mUpgradeProtocolCallback = nullptr;
10532 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10533 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)
10534 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)
;
10535
10536 // This ensures that WebSocketChannel::OnStopRequest will be
10537 // called with an error so the session is properly aborted.
10538 aStatus = rv;
10539 }
10540 }
10541
10542 return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
10543}
10544
10545nsresult nsHttpChannel::ContinueOnStopRequest(nsresult aStatus, bool aIsFromNet,
10546 bool aContentComplete) {
10547 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)
10548 ("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)
10549 "[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)
10550 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)
;
10551
10552 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ContinueOnStopRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10553( "nsHttpChannel::ContinueOnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10553 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10553( "nsHttpChannel::ContinueOnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10554 // HTTP_CHANNEL_DISPOSITION TELEMETRY
10555 ChannelDisposition chanDisposition = kHttpCanceled;
10556 // HTTP_CHANNEL_DISPOSITION_UPGRADE TELEMETRY
10557 HttpChannelDispositionUpgrade upgradeChanDisposition =
10558 HttpChannelDispositionUpgrade::cancel;
10559
10560 // HTTP 0.9 is more likely to be an error than really 0.9, so count it that
10561 // way
10562 if (mCanceled) {
10563 chanDisposition = kHttpCanceled;
10564 upgradeChanDisposition = HttpChannelDispositionUpgrade::cancel;
10565 } else if (!LoadUsedNetwork()) {
10566 chanDisposition = kHttpDisk;
10567 upgradeChanDisposition = HttpChannelDispositionUpgrade::disk;
10568 } else if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) && mResponseHead &&
10569 mResponseHead->Version() != HttpVersion::v0_9) {
10570 chanDisposition = kHttpNetOK;
10571 upgradeChanDisposition = HttpChannelDispositionUpgrade::netOk;
10572 } else if (!mTransferSize) {
10573 chanDisposition = kHttpNetEarlyFail;
10574 upgradeChanDisposition = HttpChannelDispositionUpgrade::netEarlyFail;
10575 } else {
10576 chanDisposition = kHttpNetLateFail;
10577 upgradeChanDisposition = HttpChannelDispositionUpgrade::netLateFail;
10578 }
10579 // Browser upgrading only happens on HTTPS pages for mixed passive content
10580 // when upgrading is enabled.
10581 nsCString upgradeKey;
10582 nsLiteralCString upgradeChanDispositionLabel =
10583 HttpChanDispositionToTelemetryLabel(upgradeChanDisposition);
10584 if (IsHTTPS()) {
10585 // Browser upgrading is disabled and the content is already HTTPS
10586 upgradeKey = "disabledNoReason"_ns;
10587 // Checks "security.mixed_content.upgrade_display_content" is true
10588 if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
10589 if (mLoadInfo->GetBrowserUpgradeInsecureRequests()) {
10590 // HTTP content the browser has upgraded to HTTPS
10591 mozilla::glean::networking::http_channel_disposition_enabled_upgrade
10592 .Get(upgradeChanDispositionLabel)
10593 .Add(1);
10594 upgradeKey = "enabledUpgrade"_ns;
10595 } else {
10596 // Content wasn't upgraded but is already HTTPS
10597 mozilla::glean::networking::http_channel_disposition_enabled_no_reason
10598 .Get(upgradeChanDispositionLabel)
10599 .Add(1);
10600 upgradeKey = "enabledNoReason"_ns;
10601 }
10602 } else {
10603 mozilla::glean::networking::http_channel_disposition_disabled_no_reason
10604 .Get(upgradeChanDispositionLabel)
10605 .Add(1);
10606 }
10607 // shift http to https disposition enums
10608 chanDisposition =
10609 static_cast<ChannelDisposition>(chanDisposition + kHttpsCanceled);
10610 } else if (mLoadInfo->GetBrowserWouldUpgradeInsecureRequests()) {
10611 // HTTP content the browser would upgrade to HTTPS if upgrading was
10612 // enabled
10613 mozilla::glean::networking::http_channel_disposition_disabled_upgrade
10614 .Get(upgradeChanDispositionLabel)
10615 .Add(1);
10616 upgradeKey = "disabledUpgrade"_ns;
10617 } else if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
10618 // HTTP content that wouldn't upgrade
10619 mozilla::glean::networking::http_channel_disposition_enabled_wont
10620 .Get(upgradeChanDispositionLabel)
10621 .Add(1);
10622 upgradeKey = "enabledWont"_ns;
10623 } else {
10624 mozilla::glean::networking::http_channel_disposition_disabled_wont
10625 .Get(upgradeChanDispositionLabel)
10626 .Add(1);
10627 upgradeKey = "disabledWont"_ns;
10628 }
10629
10630 glean::networking::http_channel_disposition_upgrade
10631 .Get(upgradeKey, upgradeChanDispositionLabel)
10632 .Add();
10633
10634 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)
10635 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)
;
10636 glean::http::channel_disposition.AccumulateSingleSample(chanDisposition);
10637 RecordHttpChanDispositionGlean(chanDisposition);
10638
10639 // if needed, check cache entry has all data we expect
10640 if (mCacheEntry && mCachePump && LoadConcurrentCacheAccess() &&
10641 aContentComplete) {
10642 int64_t size, contentLength;
10643 nsresult rv = CheckPartial(mCacheEntry, &size, &contentLength);
10644 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10645 if (size == int64_t(-1)) {
10646 // mayhemer TODO - we have to restart read from cache here at the size
10647 // offset
10648 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"
, 10648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")"
); do { MOZ_CrashSequence(__null, 10648); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10649 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)
10650 (" 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)
10651 "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)
;
10652 } else if (contentLength != int64_t(-1) && contentLength != size) {
10653 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)
;
10654 mCachedResponseHead = std::move(mResponseHead);
10655 // Ignore zero partial length because we also want to resume when
10656 // no data at all has been read from the cache.
10657 rv = MaybeSetupByteRangeRequest(size, contentLength, true);
10658 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest()) {
10659 // Prevent read from cache again
10660 StoreCachedContentIsValid(CachedContentValidity::Invalid);
10661 StoreCachedContentIsPartial(1);
10662
10663 // Perform the range request
10664 rv = ContinueConnect();
10665 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10666 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)
;
10667 mCachePump = nullptr;
10668 return NS_OK;
10669 }
10670 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)
10671 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)
;
10672 aStatus = NS_ERROR_NET_INTERRUPT;
10673 } else {
10674 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)
10675 ", 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)
10676 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)
;
10677 aStatus = NS_ERROR_NET_INTERRUPT;
10678 }
10679
10680 // Range-request recovery failed. Restore mResponseHead so that
10681 // it's available to late callers of Cancel (such as the ORB
10682 // async JS-validation callback)
10683 mResponseHead = std::move(mCachedResponseHead);
10684 }
10685 }
10686 }
10687
10688 StoreIsPending(false);
10689 mStatus = aStatus;
10690
10691 // perform any final cache operations before we close the cache entry.
10692 if (mCacheEntry && LoadRequestTimeInitialized()) {
10693 // New implementation just returns value of the !LoadCacheEntryIsReadOnly()
10694 // flag passed in. Old implementation checks on nsICache::ACCESS_WRITE
10695 // flag.
10696
10697 // Assume that write access is granted
10698 if (!LoadCacheEntryIsReadOnly()) {
10699 nsresult rv = FinalizeCacheEntry();
10700 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10701 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)
;
10702 }
10703 }
10704 }
10705
10706 // Register entry to the PerformanceStorage resource timing
10707 MaybeReportTimingData();
10708
10709 MaybeFlushConsoleReports();
10710
10711 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
10712 // These do allocations/frees/etc; avoid if not active
10713 mEndMarkerAdded = true;
10714
10715 nsAutoCString requestMethod;
10716 GetRequestMethod(requestMethod);
10717
10718 int32_t priority = PRIORITY_NORMAL;
10719 GetPriority(&priority);
10720
10721 uint64_t size = 0;
10722 GetEncodedBodySize(&size);
10723
10724 nsAutoCString contentType;
10725 mozilla::Maybe<mozilla::net::HttpVersion> httpVersion = Nothing();
10726 mozilla::Maybe<uint32_t> responseStatus = Nothing();
10727 if (mResponseHead) {
10728 mResponseHead->ContentType(contentType);
10729 httpVersion = Some(mResponseHead->Version());
10730 responseStatus = Some(mResponseHead->Status());
10731 }
10732
10733 profiler_add_network_marker(
10734 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_STOP,
10735 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
10736 mLoadInfo->GetInnerWindowID(),
10737 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
10738 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
10739 &mTransactionTimings, std::move(mSource),
10740 // Skip the version for a cached response: it reflects the original
10741 // fetch, not this request's connection.
10742 (mCacheDisposition == kCacheHit ||
10743 mCacheDisposition == kCacheHitViaReval)
10744 ? Nothing()
10745 : httpVersion,
10746 responseStatus, Some(nsDependentCString(contentType.get())));
10747 }
10748
10749 if (mAuthRetryPending &&
10750 StaticPrefs::network_auth_use_redirect_for_retries()) {
10751 nsresult rv = OpenRedirectChannel(aStatus);
10752 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)
10753 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)
;
10754 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10755 if (mListener) {
10756 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"
, 10757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10757); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10757 "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"
, 10757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10757); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10758 if (!LoadOnStartRequestCalled()) {
10759 nsCOMPtr<nsIStreamListener> listener(mListener);
10760 StoreOnStartRequestCalled(true);
10761 listener->OnStartRequest(this);
10762 }
10763 } else {
10764 StoreOnStartRequestCalled(true);
10765 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"
, 10765)
;
10766 }
10767 }
10768 mAuthRetryPending = false;
10769 }
10770
10771 if (LoadUsedNetwork() && !mReportedNEL) {
10772 MaybeGenerateNELReport();
10773 }
10774
10775 // notify "http-on-before-stop-request" observers
10776 gHttpHandler->OnBeforeStopRequest(this);
10777
10778 if (mListener) {
10779 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)
;
10780 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", 10781
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { MOZ_CrashSequence(__null, 10781); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10781 "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", 10781
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { MOZ_CrashSequence(__null, 10781); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10782 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"
, 10783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { MOZ_CrashSequence
(__null, 10783); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10783 "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"
, 10783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { MOZ_CrashSequence
(__null, 10783); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10784 StoreOnStopRequestCalled(true);
10785 nsCOMPtr<nsIStreamListener> listener(mListener);
10786 listener->OnStopRequest(this, aStatus);
10787 }
10788 StoreOnStopRequestCalled(true);
10789
10790 // The prefetch needs to be released on the main thread
10791 mDNSPrefetch = nullptr;
10792
10793 mRedirectChannel = nullptr;
10794
10795 // notify "http-on-stop-request" observers
10796 gHttpHandler->OnStopRequest(this);
10797
10798 RemoveAsNonTailRequest();
10799
10800 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref &&
10801 mResponseHead) {
10802 mResponseHead->ClearHeaders();
10803 }
10804 // If a preferred alt-data type was set, this signals the consumer is
10805 // interested in reading and/or writing the alt-data representation.
10806 // We need to hold a reference to the cache entry in case the listener calls
10807 // openAlternativeOutputStream() after CloseCacheEntry() clears mCacheEntry.
10808 if (!mPreferredCachedAltDataTypes.IsEmpty()) {
10809 mAltDataCacheEntry = mCacheEntry;
10810 }
10811
10812 CloseCacheEntry(!aContentComplete);
10813 mWritingToCache = false;
10814
10815 if (mLoadGroup) {
10816 mLoadGroup->RemoveRequest(this, nullptr, aStatus);
10817 }
10818
10819 // We don't need this info anymore
10820 CleanRedirectCacheChainIfNecessary();
10821
10822 ReleaseListeners();
10823
10824 // Release mUploadStream to free some memory sooner.
10825 // We release this in background thread to avoid blocking I/O operations on
10826 // main thread See Bug 1940224
10827 (void)NS_DispatchBackgroundTask(NS_NewRunnableFunction(
10828 "release HttpBaseChannel::mUploadStream",
10829 [uploadStream = std::move(mUploadStream)]() { (void)uploadStream; }));
10830
10831 return NS_OK;
10832}
10833
10834//-----------------------------------------------------------------------------
10835// nsHttpChannel::nsIStreamListener
10836//-----------------------------------------------------------------------------
10837
10838class OnTransportStatusAsyncEvent : public Runnable {
10839 public:
10840 OnTransportStatusAsyncEvent(nsITransportEventSink* aEventSink,
10841 nsresult aTransportStatus, int64_t aProgress,
10842 int64_t aProgressMax)
10843 : Runnable("net::OnTransportStatusAsyncEvent"),
10844 mEventSink(aEventSink),
10845 mTransportStatus(aTransportStatus),
10846 mProgress(aProgress),
10847 mProgressMax(aProgressMax) {
10848 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"
, 10848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "Shouldn't be created on main thread" ")"); do { MOZ_CrashSequence
(__null, 10848); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10849 }
10850
10851 NS_IMETHODvirtual nsresult Run() override {
10852 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"
, 10852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should run on main thread" ")"); do { MOZ_CrashSequence
(__null, 10852); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10853 if (mEventSink) {
10854 mEventSink->OnTransportStatus(nullptr, mTransportStatus, mProgress,
10855 mProgressMax);
10856 }
10857 return NS_OK;
10858 }
10859
10860 private:
10861 nsCOMPtr<nsITransportEventSink> mEventSink;
10862 nsresult mTransportStatus;
10863 int64_t mProgress;
10864 int64_t mProgressMax;
10865};
10866
10867NS_IMETHODIMPnsresult
10868nsHttpChannel::OnDataAvailable(nsIRequest* request, nsIInputStream* input,
10869 uint64_t offset, uint32_t count) {
10870 nsresult rv;
10871 AUTO_PROFILER_LABEL("nsHttpChannel::OnDataAvailable", NETWORK)mozilla::AutoProfilerLabel raiiObject10871( "nsHttpChannel::OnDataAvailable"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
10872 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnDataAvailable", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10873( "nsHttpChannel::OnDataAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10873 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10873( "nsHttpChannel::OnDataAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10874
10875 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)
10876 " 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)
10877 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)
;
10878
10879 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)
10880 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)
;
10881
10882 // don't send out OnDataAvailable notifications if we've been canceled.
10883 if (mCanceled) return mStatus;
10884
10885 if (mAuthRetryPending ||
10886 (request == mTransactionPump && LoadTransactionReplaced())) {
10887 uint32_t n;
10888 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &n);
10889 }
10890
10891 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"
, 10891); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "No response head in ODA!!" ")"); do { MOZ_CrashSequence
(__null, 10891); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10892
10893 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"
, 10894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { MOZ_CrashSequence
(__null, 10894); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10894 "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"
, 10894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { MOZ_CrashSequence
(__null, 10894); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10895
10896 mIsReadingFromCache = (request == mCachePump);
10897
10898 if (mListener) {
10899 //
10900 // synthesize transport progress event. we do this here since we want
10901 // to delay OnProgress events until we start streaming data. this is
10902 // crucially important since it impacts the lock icon (see bug 240053).
10903 //
10904 nsresult transportStatus;
10905 if (request == mCachePump) {
10906 transportStatus = NS_NET_STATUS_READING;
10907 } else {
10908 transportStatus = NS_NET_STATUS_RECEIVING_FROM;
10909 }
10910
10911 // mResponseHead may reference new or cached headers, but either way it
10912 // holds our best estimate of the total content length. Even in the case
10913 // of a byte range request, the content length stored in the cached
10914 // response headers is what we want to use here.
10915
10916 int64_t progressMax = -1;
10917 rv = GetContentLength(&progressMax);
10918 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10919 NS_WARNING("GetContentLength failed")NS_DebugBreak(NS_DEBUG_WARNING, "GetContentLength failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10919
)
;
10920 }
10921 int64_t progress = mLogicalOffset + count;
10922
10923 if ((progress > progressMax) && (progressMax != -1)) {
10924 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10926)
10925 "unexpected progress values - "NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10926)
10926 "is server exceeding content length?")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10926)
;
10927 }
10928
10929 // make sure params are in range for js
10930 if (!InScriptableRange(progressMax)) {
10931 progressMax = -1;
10932 }
10933
10934 if (!InScriptableRange(progress)) {
10935 progress = -1;
10936 }
10937
10938 if (NS_IsMainThread()) {
10939 OnTransportStatus(nullptr, transportStatus, progress, progressMax);
10940 } else {
10941 rv = NS_DispatchToMainThread(new OnTransportStatusAsyncEvent(
10942 this, transportStatus, progress, progressMax));
10943 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"
, 10943); return rv; } } while (false)
;
10944 }
10945
10946 //
10947 // we have to manually keep the logical offset of the stream up-to-date.
10948 // we cannot depend solely on the offset provided, since we may have
10949 // already streamed some data from another source (see, for example,
10950 // OnDoneReadingPartialCacheEntry).
10951 //
10952 int64_t offsetBefore = 0;
10953 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(input);
10954 if (seekable && NS_FAILED(seekable->Tell(&offsetBefore))((bool)(__builtin_expect(!!(NS_FAILED_impl(seekable->Tell(
&offsetBefore))), 0)))
) {
10955 seekable = nullptr;
10956 }
10957
10958 if (nsIOService::UseSocketProcess() && mTransaction) {
10959 mOnDataAvailableStartTime = mTransaction->GetDataAvailableStartTime();
10960 if (!mOnDataAvailableStartTime.IsNull()) {
10961 PerfStats::RecordMeasurement(
10962 PerfStats::Metric::OnDataAvailableSocketToParent,
10963 TimeStamp::Now() - mOnDataAvailableStartTime);
10964 }
10965 } else {
10966 mOnDataAvailableStartTime = TimeStamp::Now();
10967 }
10968 nsCOMPtr<nsIStreamListener> listener = mListener;
10969 nsresult rv = listener->OnDataAvailable(this, input, mLogicalOffset, count);
10970 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10971 // by contract mListener must read all of "count" bytes, but
10972 // nsInputStreamPump is tolerant to seekable streams that violate that
10973 // and it will redeliver incompletely read data. So we need to do
10974 // the same thing when updating the progress counter to stay in sync.
10975 int64_t offsetAfter, delta;
10976 if (seekable && NS_SUCCEEDED(seekable->Tell(&offsetAfter))((bool)(__builtin_expect(!!(!NS_FAILED_impl(seekable->Tell
(&offsetAfter))), 1)))
) {
10977 delta = offsetAfter - offsetBefore;
10978 if (delta != count) {
10979 count = delta;
10980
10981 NS_WARNING("Listener OnDataAvailable contract violation")NS_DebugBreak(NS_DEBUG_WARNING, "Listener OnDataAvailable contract violation"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10981)
;
10982 nsCOMPtr<nsIConsoleService> consoleService;
10983 consoleService = mozilla::components::Console::Service();
10984 nsAutoString message(nsLiteralString(
10985 u"http channel Listener OnDataAvailable contract violation"));
10986 if (consoleService) {
10987 consoleService->LogStringMessage(message.get());
10988 }
10989 }
10990 }
10991 mLogicalOffset += count;
10992 }
10993
10994 return rv;
10995 }
10996
10997 return NS_ERROR_ABORT;
10998}
10999
11000//-----------------------------------------------------------------------------
11001// nsHttpChannel::nsIThreadRetargetableRequest
11002//-----------------------------------------------------------------------------
11003
11004NS_IMETHODIMPnsresult
11005nsHttpChannel::RetargetDeliveryTo(nsISerialEventTarget* aNewTarget) {
11006 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"
, 11006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on main thread only" ")"); do { MOZ_CrashSequence
(__null, 11006); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11007
11008 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"
, 11008); return NS_ERROR_INVALID_ARG; } } while (false)
;
11009 if (aNewTarget->IsOnCurrentThread()) {
11010 NS_WARNING("Retargeting delivery to same thread")NS_DebugBreak(NS_DEBUG_WARNING, "Retargeting delivery to same thread"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11010)
;
11011 return NS_OK;
11012 }
11013 // Dictionary operations (saving, decompressing dcb/dcz, or using a
11014 // dictionary for decompression) require the main thread for hash
11015 // accumulation, origin metadata writes, and dictionary data access.
11016 if (mDictSaving || mIsDictionaryCompressed || mDictDecompress) {
11017 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)
11018 ("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)
11019 "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)
11020 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)
11021 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)
;
11022 return NS_ERROR_NOT_AVAILABLE;
11023 }
11024 if (!mTransactionPump && !mCachePump) {
11025 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)
11026 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)
;
11027 return NS_ERROR_NOT_AVAILABLE;
11028 }
11029
11030 nsresult rv = NS_OK;
11031 // If both cache pump and transaction pump exist, we're probably dealing
11032 // with partially cached content. So, we must be able to retarget both.
11033 nsCOMPtr<nsIThreadRetargetableRequest> retargetableCachePump;
11034 nsCOMPtr<nsIThreadRetargetableRequest> retargetableTransactionPump;
11035 if (mCachePump) {
11036 retargetableCachePump = do_QueryObject(mCachePump);
11037 // nsInputStreamPump should implement this interface.
11038 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", 11038
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableCachePump"
")"); do { MOZ_CrashSequence(__null, 11038); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11039 rv = retargetableCachePump->RetargetDeliveryTo(aNewTarget);
11040 }
11041 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mTransactionPump) {
11042 retargetableTransactionPump = do_QueryObject(mTransactionPump);
11043 // nsInputStreamPump should implement this interface.
11044 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", 11044
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableTransactionPump"
")"); do { MOZ_CrashSequence(__null, 11044); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11045 rv = retargetableTransactionPump->RetargetDeliveryTo(aNewTarget);
11046
11047 // If retarget fails for transaction pump, we must restore mCachePump.
11048 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && retargetableCachePump) {
11049 nsCOMPtr<nsISerialEventTarget> main = GetMainThreadSerialEventTarget();
11050 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", 11050
); return NS_ERROR_UNEXPECTED; } } while (false)
;
11051 rv = retargetableCachePump->RetargetDeliveryTo(main);
11052 }
11053 }
11054 return rv;
11055}
11056
11057NS_IMETHODIMPnsresult
11058nsHttpChannel::GetDeliveryTarget(nsISerialEventTarget** aEventTarget) {
11059 if (mCachePump) {
11060 return mCachePump->GetDeliveryTarget(aEventTarget);
11061 }
11062 if (mTransactionPump) {
11063 nsCOMPtr<nsIThreadRetargetableRequest> request =
11064 do_QueryInterface(mTransactionPump);
11065 return request->GetDeliveryTarget(aEventTarget);
11066 }
11067 return NS_ERROR_NOT_AVAILABLE;
11068}
11069
11070//-----------------------------------------------------------------------------
11071// nsHttpChannel::nsThreadRetargetableStreamListener
11072//-----------------------------------------------------------------------------
11073
11074NS_IMETHODIMPnsresult
11075nsHttpChannel::CheckListenerChain() {
11076 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"
, 11076); MOZ_PretendNoReturn(); } } while (0)
;
11077 nsresult rv = NS_OK;
11078 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
11079 do_QueryInterface(mListener, &rv);
11080 if (retargetableListener) {
11081 rv = retargetableListener->CheckListenerChain();
11082 }
11083 return rv;
11084}
11085
11086NS_IMETHODIMPnsresult
11087nsHttpChannel::OnDataFinished(nsresult aStatus) {
11088 nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
11089 do_QueryInterface(mListener);
11090
11091 if (listener) {
11092 return listener->OnDataFinished(aStatus);
11093 }
11094
11095 return NS_OK;
11096}
11097
11098//-----------------------------------------------------------------------------
11099// nsHttpChannel::nsITransportEventSink
11100//-----------------------------------------------------------------------------
11101
11102NS_IMETHODIMPnsresult
11103nsHttpChannel::OnTransportStatus(nsITransport* trans, nsresult status,
11104 int64_t progress, int64_t progressMax) {
11105 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"
, 11105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be on main thread only" ")"); do { MOZ_CrashSequence
(__null, 11105); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11106 // cache the progress sink so we don't have to query for it each time.
11107 if (!mProgressSink) GetCallback(mProgressSink);
11108
11109 mLastTransportStatus = status;
11110 if (status == NS_NET_STATUS_CONNECTED_TO ||
11111 status == NS_NET_STATUS_WAITING_FOR) {
11112 bool isTrr = false;
11113 bool echConfigUsed = false;
11114 if (mTransaction) {
11115 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
11116 mEffectiveTRRMode, mTRRSkipReason,
11117 echConfigUsed);
11118
11119 } else {
11120 nsCOMPtr<nsISocketTransport> socketTransport = do_QueryInterface(trans);
11121 if (socketTransport) {
11122 socketTransport->GetPeerAddr(&mPeerAddr);
11123 socketTransport->GetSelfAddr(&mSelfAddr);
11124 socketTransport->ResolvedByTRR(&isTrr);
11125 socketTransport->GetEffectiveTRRMode(&mEffectiveTRRMode);
11126 socketTransport->GetEchConfigUsed(&echConfigUsed);
11127 }
11128 }
11129
11130 StoreResolvedByTRR(isTrr);
11131 StoreEchConfigUsed(echConfigUsed);
11132 }
11133
11134 // block socket status event after Cancel or OnStopRequest has been called.
11135 if (mProgressSink && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && LoadIsPending()) {
11136 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)
11137 " 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)
11138 (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)
11139 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)
;
11140
11141 nsAutoCString host;
11142 mURI->GetHost(host);
11143 nsCOMPtr<nsIProgressEventSink> progressSink(mProgressSink);
11144 if (!(mLoadFlags & LOAD_BACKGROUND)) {
11145 progressSink->OnStatus(this, status, NS_ConvertUTF8toUTF16(host).get());
11146 } else {
11147 nsCOMPtr<nsIParentChannel> parentChannel;
11148 NS_QueryNotificationCallbacks(this, parentChannel);
11149 // If the event sink is |HttpChannelParent|, we have to send status
11150 // events to it even if LOAD_BACKGROUND is set. |HttpChannelParent|
11151 // needs to be aware of whether the status is
11152 // |NS_NET_STATUS_RECEIVING_FROM| or |NS_NET_STATUS_READING|.
11153 // LOAD_BACKGROUND is checked again in |HttpChannelChild|, so the final
11154 // consumer won't get this event.
11155 if (SameCOMIdentity(parentChannel, mProgressSink)) {
11156 progressSink->OnStatus(this, status, NS_ConvertUTF8toUTF16(host).get());
11157 }
11158 }
11159
11160 if (progress > 0) {
11161 if ((progress > progressMax) && (progressMax != -1)) {
11162 NS_WARNING("unexpected progress values")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values",
nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11162)
;
11163 }
11164
11165 // Try to get mProgressSink if it was nulled out during OnStatus.
11166 if (!mProgressSink) {
11167 GetCallback(mProgressSink);
11168 progressSink = mProgressSink;
11169 }
11170 if (progressSink) {
11171 progressSink->OnProgress(this, progress, progressMax);
11172 }
11173 }
11174 }
11175
11176 return NS_OK;
11177}
11178
11179//-----------------------------------------------------------------------------
11180// nsHttpChannel::nsICacheInfoChannel
11181//-----------------------------------------------------------------------------
11182
11183NS_IMETHODIMPnsresult
11184nsHttpChannel::IsFromCache(bool* value) {
11185 if (!LoadIsPending()) return NS_ERROR_NOT_AVAILABLE;
11186
11187 // return false if reading a partial cache entry; the data isn't
11188 // entirely from the cache!
11189 *value = (mCachePump || (mLoadFlags & LOAD_ONLY_IF_MODIFIED)) &&
11190 CachedContentIsValid() && !LoadCachedContentIsPartial();
11191 return NS_OK;
11192}
11193
11194NS_IMETHODIMPnsresult
11195nsHttpChannel::HasCacheEntry(bool* value) {
11196 *value = !!mCacheEntry;
11197 return NS_OK;
11198}
11199
11200NS_IMETHODIMPnsresult
11201nsHttpChannel::GetCacheEntryId(uint64_t* aCacheEntryId) {
11202 if (!mCacheEntry || NS_FAILED(mCacheEntry->GetCacheEntryId(aCacheEntryId))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCacheEntry->GetCacheEntryId
(aCacheEntryId))), 0)))
) {
11203 return NS_ERROR_NOT_AVAILABLE;
11204 }
11205
11206 return NS_OK;
11207}
11208
11209NS_IMETHODIMPnsresult
11210nsHttpChannel::GetCacheTokenFetchCount(uint32_t* _retval) {
11211 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", 11211
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11212 nsCOMPtr<nsICacheEntry> cacheEntry =
11213 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11214 if (!cacheEntry) {
11215 return NS_ERROR_NOT_AVAILABLE;
11216 }
11217
11218 return cacheEntry->GetFetchCount(_retval);
11219}
11220
11221NS_IMETHODIMPnsresult
11222nsHttpChannel::GetCacheTokenExpirationTime(uint32_t* _retval) {
11223 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", 11223
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11224 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
11225
11226 return mCacheEntry->GetExpirationTime(_retval);
11227}
11228
11229NS_IMETHODIMPnsresult
11230nsHttpChannel::SetAllowStaleCacheContent(bool aAllowStaleCacheContent) {
11231 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)
11232 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)
;
11233 StoreAllowStaleCacheContent(aAllowStaleCacheContent);
11234 return NS_OK;
11235}
11236NS_IMETHODIMPnsresult
11237nsHttpChannel::GetAllowStaleCacheContent(bool* aAllowStaleCacheContent) {
11238 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"
, 11238); return NS_ERROR_INVALID_ARG; } } while (false)
;
11239 *aAllowStaleCacheContent = LoadAllowStaleCacheContent();
11240 return NS_OK;
11241}
11242
11243NS_IMETHODIMPnsresult
11244nsHttpChannel::SetForceValidateCacheContent(bool aForceValidateCacheContent) {
11245 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)
11246 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)
;
11247 StoreForceValidateCacheContent(aForceValidateCacheContent);
11248 return NS_OK;
11249}
11250NS_IMETHODIMPnsresult
11251nsHttpChannel::GetForceValidateCacheContent(bool* aForceValidateCacheContent) {
11252 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"
, 11252); return NS_ERROR_INVALID_ARG; } } while (false)
;
11253 *aForceValidateCacheContent = LoadForceValidateCacheContent();
11254 return NS_OK;
11255}
11256
11257NS_IMETHODIMPnsresult
11258nsHttpChannel::SetPreferCacheLoadOverBypass(bool aPreferCacheLoadOverBypass) {
11259 StorePreferCacheLoadOverBypass(aPreferCacheLoadOverBypass);
11260 return NS_OK;
11261}
11262NS_IMETHODIMPnsresult
11263nsHttpChannel::GetPreferCacheLoadOverBypass(bool* aPreferCacheLoadOverBypass) {
11264 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"
, 11264); return NS_ERROR_INVALID_ARG; } } while (false)
;
11265 *aPreferCacheLoadOverBypass = LoadPreferCacheLoadOverBypass();
11266 return NS_OK;
11267}
11268
11269NS_IMETHODIMPnsresult
11270nsHttpChannel::PreferAlternativeDataType(
11271 const nsACString& aType, const nsACString& aContentType,
11272 PreferredAlternativeDataDeliveryType aDeliverAltData) {
11273 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11273); 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"
, 11273, 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"
, 11273); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11273); 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"
, 11273); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
11274 mPreferredCachedAltDataTypes.AppendElement(PreferredAlternativeDataTypeParams(
11275 nsCString(aType), nsCString(aContentType), aDeliverAltData));
11276 return NS_OK;
11277}
11278
11279const nsTArray<PreferredAlternativeDataTypeParams>&
11280nsHttpChannel::PreferredAlternativeDataTypes() {
11281 return mPreferredCachedAltDataTypes;
11282}
11283
11284NS_IMETHODIMPnsresult
11285nsHttpChannel::GetAlternativeDataType(nsACString& aType) {
11286 // must be called during or after OnStartRequest
11287 if (!LoadAfterOnStartRequestBegun()) {
11288 return NS_ERROR_NOT_AVAILABLE;
11289 }
11290 aType = mAvailableCachedAltDataType;
11291 return NS_OK;
11292}
11293
11294class CacheEntryWriteHandle : public nsICacheEntryWriteHandle {
11295 virtual ~CacheEntryWriteHandle() = default;
11296
11297 public:
11298 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:
11299 NS_DECL_NSICACHEENTRYWRITEHANDLEvirtual nsresult OpenAlternativeOutputStream(const nsACString
& type, int64_t predictedSize, nsIAsyncOutputStream **_retval
) override;
11300
11301 explicit CacheEntryWriteHandle(nsICacheEntry* aCacheEntry)
11302 : mCacheEntry(aCacheEntry) {
11303 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"
, 11303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 11303); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11304 }
11305
11306 private:
11307 nsCOMPtr<nsICacheEntry> mCacheEntry;
11308};
11309
11310NS_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"
, 11310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 11310
); __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"
, 11310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CacheEntryWriteHandle\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11310); __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; }
11311NS_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"
, 11311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 11311
); __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"
, 11311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CacheEntryWriteHandle\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11311); __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; }
11312NS_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"
, 11312); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
11313 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
11314 NS_INTERFACE_MAP_ENTRY(nsICacheEntryWriteHandle)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheEntryWriteHandle>)) foundInterface
= static_cast<nsICacheEntryWriteHandle*>(this); else
11315NS_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"
, 11315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 11315); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); status
= NS_NOINTERFACE; } else { (foundInterface)->AddRef(); status
= NS_OK; } *aInstancePtr = foundInterface; return status; }
11316
11317NS_IMETHODIMPnsresult
11318CacheEntryWriteHandle::OpenAlternativeOutputStream(
11319 const nsACString& type, int64_t predictedSize,
11320 nsIAsyncOutputStream** _retval) {
11321 nsresult rv =
11322 mCacheEntry->OpenAlternativeOutputStream(type, predictedSize, _retval);
11323 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11324 mCacheEntry->SetMetaDataElement("alt-data-from-child", nullptr);
11325 }
11326 return rv;
11327}
11328
11329NS_IMETHODIMPnsresult
11330nsHttpChannel::GetCacheEntryWriteHandle(nsICacheEntryWriteHandle** _retval) {
11331 nsCOMPtr<nsICacheEntry> cacheEntry =
11332 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11333 if (!cacheEntry) {
11334 return NS_ERROR_NOT_AVAILABLE;
11335 }
11336
11337 nsCOMPtr<nsICacheEntryWriteHandle> handle =
11338 new CacheEntryWriteHandle(cacheEntry);
11339 handle.forget(_retval);
11340 return NS_OK;
11341}
11342
11343NS_IMETHODIMPnsresult
11344nsHttpChannel::OpenAlternativeOutputStream(const nsACString& type,
11345 int64_t predictedSize,
11346 nsIAsyncOutputStream** _retval) {
11347 // OnStopRequest will clear mCacheEntry, but we may use mAltDataCacheEntry
11348 // if the consumer called PreferAlternativeDataType()
11349 nsCOMPtr<nsICacheEntry> cacheEntry =
11350 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11351 if (!cacheEntry) {
11352 return NS_ERROR_NOT_AVAILABLE;
11353 }
11354 nsresult rv =
11355 cacheEntry->OpenAlternativeOutputStream(type, predictedSize, _retval);
11356 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11357 // Clear this metadata flag in case it exists.
11358 // The caller of this method may set it again.
11359 cacheEntry->SetMetaDataElement("alt-data-from-child", nullptr);
11360 }
11361 return rv;
11362}
11363
11364NS_IMETHODIMPnsresult
11365nsHttpChannel::GetOriginalInputStream(nsIInputStreamReceiver* aReceiver) {
11366 if (aReceiver == nullptr) {
11367 return NS_ERROR_INVALID_ARG;
11368 }
11369 nsCOMPtr<nsIInputStream> inputStream;
11370
11371 nsCOMPtr<nsICacheEntry> cacheEntry =
11372 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11373 if (cacheEntry) {
11374 cacheEntry->OpenInputStream(0, getter_AddRefs(inputStream));
11375 }
11376 aReceiver->OnInputStreamReady(inputStream);
11377 return NS_OK;
11378}
11379
11380NS_IMETHODIMPnsresult
11381nsHttpChannel::GetAlternativeDataInputStream(nsIInputStream** aInputStream) {
11382 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"
, 11382); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11383
11384 *aInputStream = nullptr;
11385
11386 nsCOMPtr<nsICacheEntry> cacheEntry =
11387 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11388 if (!mAvailableCachedAltDataType.IsEmpty() && cacheEntry) {
11389 nsresult rv = cacheEntry->OpenAlternativeInputStream(
11390 mAvailableCachedAltDataType, aInputStream);
11391 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"
, 11391); return rv; } } while (false)
;
11392 }
11393 return NS_OK;
11394}
11395
11396//-----------------------------------------------------------------------------
11397// nsHttpChannel::nsICachingChannel
11398//-----------------------------------------------------------------------------
11399
11400NS_IMETHODIMPnsresult
11401nsHttpChannel::GetCacheToken(nsISupports** token) {
11402 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", 11402
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11403 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
11404 return CallQueryInterface(mCacheEntry, token);
11405}
11406
11407NS_IMETHODIMPnsresult
11408nsHttpChannel::SetCacheToken(nsISupports* token) {
11409 return NS_ERROR_NOT_IMPLEMENTED;
11410}
11411
11412NS_IMETHODIMPnsresult
11413nsHttpChannel::GetCacheKey(uint32_t* key) {
11414 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"
, 11414); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11415
11416 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)
;
11417
11418 *key = mPostID;
11419 return NS_OK;
11420}
11421
11422NS_IMETHODIMPnsresult
11423nsHttpChannel::SetCacheKey(uint32_t key) {
11424 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)
;
11425
11426 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11426); 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"
, 11426, 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"
, 11426); } } 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", 11426
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 11426); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
11427
11428 mPostID = key;
11429 return NS_OK;
11430}
11431
11432NS_IMETHODIMPnsresult
11433nsHttpChannel::GetCacheOnlyMetadata(bool* aOnlyMetadata) {
11434 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"
, 11434); return NS_ERROR_INVALID_ARG; } } while (false)
;
11435 *aOnlyMetadata = LoadCacheOnlyMetadata();
11436 return NS_OK;
11437}
11438
11439NS_IMETHODIMPnsresult
11440nsHttpChannel::SetCacheOnlyMetadata(bool aOnlyMetadata) {
11441 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)
11442 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)
;
11443
11444 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11444); 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"
, 11444, 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"
, 11444); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11444); 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"
, 11444); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
11445
11446 StoreCacheOnlyMetadata(aOnlyMetadata);
11447 if (aOnlyMetadata) {
11448 mLoadFlags |= LOAD_ONLY_IF_MODIFIED;
11449 }
11450
11451 return NS_OK;
11452}
11453
11454NS_IMETHODIMPnsresult
11455nsHttpChannel::GetPin(bool* aPin) {
11456 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", 11456
); return NS_ERROR_INVALID_ARG; } } while (false)
;
11457 *aPin = LoadPinCacheContent();
11458 return NS_OK;
11459}
11460
11461NS_IMETHODIMPnsresult
11462nsHttpChannel::SetPin(bool aPin) {
11463 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)
;
11464
11465 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11465); 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"
, 11465, 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"
, 11465); } } 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", 11465
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 11465); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
11466
11467 StorePinCacheContent(aPin);
11468 return NS_OK;
11469}
11470
11471NS_IMETHODIMPnsresult
11472nsHttpChannel::ForceCacheEntryValidFor(uint32_t aSecondsToTheFuture) {
11473 if (!mCacheEntry) {
11474 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)
11475 ("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)
11476 "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)
11477 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
11478 } else {
11479 mCacheEntry->ForceValidFor(aSecondsToTheFuture);
11480
11481 nsAutoCString key;
11482 mCacheEntry->GetKey(key);
11483
11484 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)
11485 ("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)
11486 "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)
11487 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)
;
11488 }
11489
11490 return NS_OK;
11491}
11492
11493//-----------------------------------------------------------------------------
11494// nsHttpChannel::nsIResumableChannel
11495//-----------------------------------------------------------------------------
11496
11497NS_IMETHODIMPnsresult
11498nsHttpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) {
11499 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)
11500 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)
;
11501 mEntityID = aEntityID;
11502 mStartPos = aStartPos;
11503 StoreResuming(true);
11504 return NS_OK;
11505}
11506
11507nsresult nsHttpChannel::DoAuthRetry(
11508 HttpTransactionShell* aTransWithStickyConn,
11509 const std::function<nsresult(nsHttpChannel*, nsresult)>&
11510 aContinueOnStopRequestFunc) {
11511 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)
11512 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)
;
11513
11514 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"
, 11514); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mTransaction"
") (" "should not have a transaction" ")"); do { MOZ_CrashSequence
(__null, 11514); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11515
11516 // Clear security info so it can be repopulated by the retried connection.
11517 mSecurityInfo = nullptr;
11518
11519 // Note that we don't have to toggle |IsPending| anymore. See the reasons
11520 // below.
11521 // 1. We can't suspend the channel during "http-on-modify-request"
11522 // when |IsPending| is false.
11523 // 2. We don't check |IsPending| in SetRequestHeader now.
11524
11525 // Reset RequestObserversCalled because we've probably called the request
11526 // observers once already.
11527 StoreRequestObserversCalled(false);
11528
11529 // fetch cookies, and add them to the request header.
11530 // the server response could have included cookies that must be sent with
11531 // this authentication attempt (bug 84794).
11532 // TODO: save cookies from auth response and send them here (bug 572151).
11533 AddCookiesToRequest();
11534
11535 // notify "http-on-modify-request" observers
11536 CallOnModifyRequestObservers();
11537
11538 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
11539 return CallOrWaitForResume(
11540 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
11541 return self->ContinueDoAuthRetry(trans, aContinueOnStopRequestFunc);
11542 });
11543}
11544
11545nsresult nsHttpChannel::ContinueDoAuthRetry(
11546 HttpTransactionShell* aTransWithStickyConn,
11547 const std::function<nsresult(nsHttpChannel*, nsresult)>&
11548 aContinueOnStopRequestFunc) {
11549 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)
;
11550 StoreIsPending(true);
11551
11552 // get rid of the old response headers
11553 mResponseHead = nullptr;
11554
11555 // rewind the upload stream
11556 if (mUploadStream) {
11557 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
11558 nsresult rv = NS_ERROR_NO_INTERFACE;
11559 if (seekable) {
11560 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
11561 }
11562
11563 // This should not normally happen, but it's possible that big memory
11564 // blobs originating in the other process can't be rewinded.
11565 // In that case we just fail the request, otherwise the content length
11566 // will not match and this load will never complete.
11567 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"
, 11567); return rv; } } while (false)
;
11568 }
11569
11570 // always set sticky connection flag
11571 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
11572 // and when needed, allow restart regardless the sticky flag
11573 if (LoadAuthConnectionRestartable()) {
11574 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)
;
11575 mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
11576 StoreAuthConnectionRestartable(false);
11577 } else {
11578 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)
;
11579 mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
11580 }
11581
11582 // notify "http-on-before-connect" observers
11583 gHttpHandler->OnBeforeConnect(this);
11584
11585 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
11586 return CallOrWaitForResume(
11587 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
11588 nsresult rv = self->DoConnect(trans);
11589 return aContinueOnStopRequestFunc(self, rv);
11590 });
11591}
11592
11593//-----------------------------------------------------------------------------
11594// nsHttpChannel::nsIAsyncVerifyRedirectCallback
11595//-----------------------------------------------------------------------------
11596
11597nsresult nsHttpChannel::WaitForRedirectCallback() {
11598 nsresult rv;
11599 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)
;
11600
11601 if (mTransactionPump) {
11602 rv = mTransactionPump->Suspend();
11603 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"
, 11603); return rv; } } while (false)
;
11604 }
11605 if (mCachePump) {
11606 rv = mCachePump->Suspend();
11607 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && mTransactionPump) {
11608#ifdef DEBUG1
11609 nsresult resume =
11610#endif
11611 mTransactionPump->Resume();
11612 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"
, 11612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(resume)), 1)))"
") (" "Failed to resume transaction pump" ")"); do { MOZ_CrashSequence
(__null, 11612); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11613 }
11614 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"
, 11614); return rv; } } while (false)
;
11615 }
11616
11617 StoreWaitingForRedirectCallback(true);
11618 return NS_OK;
11619}
11620
11621NS_IMETHODIMPnsresult
11622nsHttpChannel::OnRedirectVerifyCallback(nsresult result) {
11623 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)
11624 ("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)
11625 "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)
11626 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)
11627 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)
;
11628 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"
, 11629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { MOZ_CrashSequence(__null, 11629); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11629 "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"
, 11629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { MOZ_CrashSequence(__null, 11629); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11630 StoreWaitingForRedirectCallback(false);
11631
11632 if (mCanceled && NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) result = NS_BINDING_ABORTED;
11633
11634 for (uint32_t i = mRedirectFuncStack.Length(); i > 0;) {
11635 --i;
11636 // Pop the last function pushed to the stack
11637 nsContinueRedirectionFunc func = mRedirectFuncStack.PopLastElement();
11638
11639 // Call it with the result we got from the callback or the deeper
11640 // function call.
11641 result = (this->*func)(result);
11642
11643 // If a new function has been pushed to the stack and placed us in the
11644 // waiting state, we need to break the chain and wait for the callback
11645 // again.
11646 if (LoadWaitingForRedirectCallback()) break;
11647 }
11648
11649 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
11650 // First, cancel this channel if we are in failure state to set mStatus
11651 // and let it be propagated to pumps.
11652 Cancel(result);
11653 }
11654
11655 if (!LoadWaitingForRedirectCallback()) {
11656 // We are not waiting for the callback. At this moment we must release
11657 // reference to the redirect target channel, otherwise we may leak.
11658 // However, if we are redirecting due to auth retries, we open the
11659 // redirected channel after OnStopRequest. In that case we should not
11660 // release the reference
11661 if (!StaticPrefs::network_auth_use_redirect_for_retries() ||
11662 !mAuthRetryPending) {
11663 mRedirectChannel = nullptr;
11664 }
11665 }
11666
11667 // We always resume the pumps here. If all functions on stack have been
11668 // called we need OnStopRequest to be triggered, and if we broke out of the
11669 // loop above (and are thus waiting for a new callback) the suspension
11670 // count must be balanced in the pumps.
11671 if (mTransactionPump) mTransactionPump->Resume();
11672 if (mCachePump) mCachePump->Resume();
11673
11674 return result;
11675}
11676
11677void nsHttpChannel::PushRedirectAsyncFunc(nsContinueRedirectionFunc func) {
11678 mRedirectFuncStack.AppendElement(func);
11679}
11680
11681void nsHttpChannel::PopRedirectAsyncFunc(nsContinueRedirectionFunc func) {
11682 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"
, 11683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { MOZ_CrashSequence(__null, 11683); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11683 "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"
, 11683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { MOZ_CrashSequence(__null, 11683); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11684
11685 mRedirectFuncStack.RemoveLastElement();
11686}
11687
11688//-----------------------------------------------------------------------------
11689// nsIDNSListener functions
11690//-----------------------------------------------------------------------------
11691
11692NS_IMETHODIMPnsresult
11693nsHttpChannel::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
11694 nsresult status) {
11695 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"
, 11695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { MOZ_CrashSequence
(__null, 11695); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11696
11697 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)
11698 ("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)
11699 "%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)
11700 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)
11701 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)
11702 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)
;
11703
11704 // Unset DNS cache refresh if it was requested,
11705 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
11706 mCaps &= ~NS_HTTP_REFRESH_DNS(1 << 3);
11707 if (mTransaction) {
11708 mTransaction->SetDNSWasRefreshed();
11709 }
11710 }
11711
11712 if (!mDNSBlockingPromise.IsEmpty()) {
11713 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
11714 nsCOMPtr<nsIDNSRecord> record(rec);
11715 mDNSBlockingPromise.Resolve(record, __func__);
11716 } else {
11717 mDNSBlockingPromise.Reject(status, __func__);
11718 }
11719 }
11720
11721 return NS_OK;
11722}
11723
11724void nsHttpChannel::OnHTTPSRRAvailable(nsIDNSHTTPSSVCRecord* aRecord) {
11725 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"
, 11725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { MOZ_CrashSequence
(__null, 11725); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11726
11727 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)
11728 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)
;
11729
11730 if (mHTTPSSVCRecord) {
11731 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"
, 11731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"OnHTTPSRRAvailable called twice!" ")"); do { MOZ_CrashSequence
(__null, 11731); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11732 return;
11733 }
11734
11735 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
11736 mHTTPSSVCRecord.emplace(std::move(record));
11737 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& httprr = mHTTPSSVCRecord.ref();
11738
11739 if (LoadWaitHTTPSSVCRecord()) {
11740 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", 11740
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mURI->SchemeIs(\"http\")"
")"); do { MOZ_CrashSequence(__null, 11740); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11741
11742 StoreWaitHTTPSSVCRecord(false);
11743 nsresult rv = ContinueOnBeforeConnect(!!httprr, mStatus, !!httprr);
11744 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11745 CloseCacheEntry(false);
11746 (void)AsyncAbort(rv);
11747 }
11748 } else {
11749 // This channel is not canceled and the transaction is not created.
11750 if (httprr && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mTransaction &&
11751 (mFirstResponseSource != RESPONSE_FROM_CACHE)) {
11752 bool hasIPAddress = false;
11753 (void)httprr->GetHasIPAddresses(&hasIPAddress);
11754 glean::http::dns_httpssvc_record_receiving_stage.AccumulateSingleSample(
11755 hasIPAddress ? HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_0
11756 : HTTPSSVC_WITHOUT_IPHINT_RECEIVED_STAGE_0);
11757 StoreHTTPSSVCTelemetryReported(true);
11758 }
11759 }
11760}
11761
11762//-----------------------------------------------------------------------------
11763// nsHttpChannel internal functions
11764//-----------------------------------------------------------------------------
11765
11766// Creates an URI to the given location using current URI for base and charset
11767nsresult nsHttpChannel::CreateNewURI(const char* loc, nsIURI** newURI) {
11768 nsCOMPtr<nsIIOService> ioService;
11769 nsresult rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
11770 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
11771
11772 return ioService->NewURI(nsDependentCString(loc), nullptr, mURI, newURI);
11773}
11774
11775void nsHttpChannel::MaybeInvalidateCacheEntryForSubsequentGet() {
11776 // See RFC 2616 section 5.1.1. These are considered valid
11777 // methods which DO NOT invalidate cache-entries for the
11778 // referred resource. POST, PUT and DELETE as well as any
11779 // other method not listed here will potentially invalidate
11780 // any cached copy of the resource
11781 if (mRequestHead.IsGet() || mRequestHead.IsOptions() ||
11782 mRequestHead.IsHead() || mRequestHead.IsTrace() ||
11783 mRequestHead.IsConnect()) {
11784 return;
11785 }
11786
11787 // Invalidate the request-uri.
11788 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
11789 nsAutoCString key;
11790 mURI->GetAsciiSpec(key);
11791 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)
11792 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)
;
11793 }
11794
11795 DoInvalidateCacheEntry(mURI);
11796
11797 // Invalidate Location-header if set
11798 nsAutoCString location;
11799 (void)mResponseHead->GetHeader(nsHttp::Location, location);
11800 if (!location.IsEmpty()) {
11801 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)
;
11802 InvalidateCacheEntryForLocation(location.get());
11803 }
11804
11805 // Invalidate Content-Location-header if set
11806 (void)mResponseHead->GetHeader(nsHttp::Content_Location, location);
11807 if (!location.IsEmpty()) {
11808 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)
;
11809 InvalidateCacheEntryForLocation(location.get());
11810 }
11811}
11812
11813void nsHttpChannel::InvalidateCacheEntryForLocation(const char* location) {
11814 nsAutoCString tmpCacheKey, tmpSpec;
11815 nsCOMPtr<nsIURI> resultingURI;
11816 nsresult rv = CreateNewURI(location, getter_AddRefs(resultingURI));
11817 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && HostPartIsTheSame(resultingURI)) {
11818 DoInvalidateCacheEntry(resultingURI);
11819 } else {
11820 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)
;
11821 }
11822}
11823
11824void nsHttpChannel::DoInvalidateCacheEntry(nsIURI* aURI) {
11825 // NOTE:
11826 // Following comments 24,32 and 33 in bug #327765, we only care about
11827 // the cache in the protocol-handler.
11828 // The logic below deviates from the original logic in OpenCacheEntry on
11829 // one point by using only READ_ONLY access-policy. I think this is safe.
11830
11831 nsresult rv;
11832
11833 nsAutoCString key;
11834 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
11835 aURI->GetAsciiSpec(key);
11836 }
11837
11838 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)
;
11839
11840 nsCOMPtr<nsICacheStorageService> cacheStorageService(
11841 components::CacheStorage::Service());
11842 rv = cacheStorageService ? NS_OK : NS_ERROR_FAILURE;
11843
11844 nsCOMPtr<nsICacheStorage> cacheStorage;
11845 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11846 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
11847 rv = cacheStorageService->DiskCacheStorage(info,
11848 getter_AddRefs(cacheStorage));
11849 }
11850
11851 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11852 rv = cacheStorage->AsyncDoomURI(aURI, ""_ns, nullptr);
11853 }
11854
11855 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)
11856 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)
;
11857}
11858
11859void nsHttpChannel::AsyncOnExamineCachedResponse() {
11860 gHttpHandler->OnExamineCachedResponse(this);
11861}
11862
11863void nsHttpChannel::UpdateAggregateCallbacks() {
11864 if (!mTransaction) {
11865 return;
11866 }
11867 nsCOMPtr<nsIInterfaceRequestor> callbacks;
11868 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
11869 GetCurrentSerialEventTarget(),
11870 getter_AddRefs(callbacks));
11871 mTransaction->SetSecurityCallbacks(callbacks);
11872}
11873
11874NS_IMETHODIMPnsresult
11875nsHttpChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
11876 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"
, 11876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { MOZ_CrashSequence(__null, 11876
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
11877
11878 nsresult rv = HttpBaseChannel::SetLoadGroup(aLoadGroup);
11879 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11880 UpdateAggregateCallbacks();
11881 }
11882 return rv;
11883}
11884
11885NS_IMETHODIMPnsresult
11886nsHttpChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
11887 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"
, 11887); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { MOZ_CrashSequence(__null, 11887
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
11888
11889 nsresult rv = HttpBaseChannel::SetNotificationCallbacks(aCallbacks);
11890 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11891 UpdateAggregateCallbacks();
11892 }
11893 return rv;
11894}
11895
11896bool nsHttpChannel::AwaitingCacheCallbacks() {
11897 return LoadWaitForCacheEntry() != 0;
11898}
11899
11900// static
11901bool nsHttpChannel::IsRedirectStatus(uint32_t status) {
11902 // 305 disabled as a security measure (see bug 187996).
11903 return status == 301 || status == 302 || status == 303 || status == 307 ||
11904 status == 308;
11905}
11906
11907void nsHttpChannel::SetCouldBeSynthesized() {
11908 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", 11908
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
")"); do { MOZ_CrashSequence(__null, 11908); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11909 StoreResponseCouldBeSynthesized(true);
11910}
11911
11912NS_IMETHODIMPnsresult
11913nsHttpChannel::OnPreflightSucceeded() {
11914 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"
, 11914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { MOZ_CrashSequence
(__null, 11914); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11915 StoreIsCorsPreflightDone(1);
11916 mPreflightChannel = nullptr;
11917
11918 return ContinueConnect();
11919}
11920
11921NS_IMETHODIMPnsresult
11922nsHttpChannel::OnPreflightFailed(nsresult aError) {
11923 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"
, 11923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { MOZ_CrashSequence
(__null, 11923); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11924 StoreIsCorsPreflightDone(1);
11925 mPreflightChannel = nullptr;
11926
11927 CloseCacheEntry(false);
11928 (void)AsyncAbort(aError);
11929 return NS_OK;
11930}
11931
11932nsresult nsHttpChannel::CallOrWaitForResume(
11933 const std::function<nsresult(nsHttpChannel*)>& aFunc) {
11934 if (mCanceled) {
11935 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", 11935
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))"
")"); do { MOZ_CrashSequence(__null, 11935); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11936 return mStatus;
11937 }
11938
11939 if (mSuspendCount) {
11940 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)
;
11941 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", 11941
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume" ")"
); do { MOZ_CrashSequence(__null, 11941); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11942 mCallOnResume = aFunc;
11943 return NS_OK;
11944 }
11945
11946 return aFunc(this);
11947}
11948
11949// This is loosely based on:
11950// https://fetch.spec.whatwg.org/#serializing-a-request-origin
11951static bool HasNullRequestOrigin(nsHttpChannel* aChannel, nsIURI* aURI,
11952 bool isAddonRequest) {
11953 // Step 1. If request has a redirect-tainted origin, then return "null".
11954 if (aChannel->HasRedirectTaintedOrigin()) {
11955 return true;
11956 }
11957
11958 // Non-standard: Only allow HTTP and HTTPS origins.
11959 if (!ReferrerInfo::IsReferrerSchemeAllowed(aURI)) {
11960 // And moz-extension: for add-on initiated requests.
11961 if (!aURI->SchemeIs("moz-extension") || !isAddonRequest) {
11962 return true;
11963 }
11964 }
11965
11966 // Non-standard: Hide onion URLs.
11967 if (StaticPrefs::network_http_referer_hideOnionSource()) {
11968 nsAutoCString host;
11969 if (NS_SUCCEEDED(aURI->GetAsciiHost(host))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aURI->GetAsciiHost
(host))), 1)))
&&
11970 StringEndsWith(host, ".onion"_ns)) {
11971 return ReferrerInfo::IsCrossOriginRequest(aChannel);
11972 }
11973 }
11974
11975 // Step 2. Return request’s origin, serialized.
11976 return false;
11977}
11978
11979// Step 8.12. of HTTP-network-or-cache fetch
11980//
11981// https://fetch.spec.whatwg.org/#append-a-request-origin-header
11982void nsHttpChannel::SetOriginHeader() {
11983 auto* triggeringPrincipal =
11984 BasePrincipal::Cast(mLoadInfo->TriggeringPrincipal());
11985
11986 if (triggeringPrincipal->IsSystemPrincipal()) {
11987 // We can't infer an Origin header from the system principal,
11988 // this means system requests use whatever Origin header was specified.
11989 return;
11990 }
11991 bool isAddonRequest = triggeringPrincipal->AddonPolicy() ||
11992 triggeringPrincipal->ContentScriptAddonPolicy();
11993
11994 // Non-standard: Handle already existing Origin header.
11995 nsAutoCString existingHeader;
11996 (void)mRequestHead.GetHeader(nsHttp::Origin, existingHeader);
11997 if (!existingHeader.IsEmpty()) {
11998 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)
;
11999 auto const shouldNullifyOriginHeader =
12000 [&existingHeader, isAddonRequest](nsHttpChannel* aChannel) {
12001 nsCOMPtr<nsIURI> uri;
12002 nsresult rv = NS_NewURI(getter_AddRefs(uri), existingHeader);
12003 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12004 return false;
12005 }
12006
12007 if (HasNullRequestOrigin(aChannel, uri, isAddonRequest)) {
12008 return true;
12009 }
12010
12011 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
12012 if (info->GetTainting() == mozilla::LoadTainting::CORS) {
12013 return false;
12014 }
12015
12016 return ReferrerInfo::ShouldSetNullOriginHeader(aChannel, uri);
12017 };
12018
12019 if (!existingHeader.EqualsLiteral("null") &&
12020 shouldNullifyOriginHeader(this)) {
12021 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)
;
12022 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", 12023
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { MOZ_CrashSequence(__null, 12023); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
12023 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", 12023
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { MOZ_CrashSequence(__null, 12023); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12024 }
12025 return;
12026 }
12027
12028 if (StaticPrefs::network_http_sendOriginHeader() == 0) {
12029 // Custom user setting: 0 means never send Origin header.
12030 return;
12031 }
12032
12033 // Step 2. Let serializedOrigin be the result of byte-serializing a request
12034 // origin with request.
12035 nsAutoCString serializedOrigin;
12036 nsCOMPtr<nsIURI> uri;
12037 {
12038 if (NS_FAILED(triggeringPrincipal->GetURI(getter_AddRefs(uri)))((bool)(__builtin_expect(!!(NS_FAILED_impl(triggeringPrincipal
->GetURI(getter_AddRefs(uri)))), 0)))
) {
12039 return;
12040 }
12041
12042 if (!uri) {
12043 if (isAddonRequest) {
12044 // For add-on compatibility prefer sending no header at all
12045 // instead of `Origin: null`.
12046 return;
12047 }
12048
12049 // Otherwise use "null" when the triggeringPrincipal's URI is nullptr.
12050 serializedOrigin.AssignLiteral("null");
12051 } else if (HasNullRequestOrigin(this, uri, isAddonRequest)) {
12052 serializedOrigin.AssignLiteral("null");
12053 } else {
12054 nsContentUtils::GetWebExposedOriginSerialization(uri, serializedOrigin);
12055 }
12056 }
12057
12058 // Step 3. If request’s response tainting is "cors" or request’s mode is
12059 // "websocket", then append (`Origin`, serializedOrigin) to request’s header
12060 // list.
12061 //
12062 // Note: We don't handle "websocket" here (yet?).
12063 if (mLoadInfo->GetTainting() == mozilla::LoadTainting::CORS) {
12064 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", 12065
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12065); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
12065 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", 12065
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12065); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12066 return;
12067 }
12068
12069 // Step 4. Otherwise, if request’s method is neither `GET` nor `HEAD`, then:
12070 if (mRequestHead.IsGet() || mRequestHead.IsHead()) {
12071 // Modified Step 4 in case storage-access-headers are enabled
12072 if (!StaticPrefs::dom_storage_access_enabled() ||
12073 !StaticPrefs::dom_storage_access_headers_enabled()) {
12074 // proceed with unmodified fetch spec
12075 return;
12076 } else {
12077 // the result of getting `Sec-Fetch-Storage-Access` from request’s header
12078 // list is "inactive"
12079 nsAutoCString storageAccess;
12080 nsresult rv =
12081 GetRequestHeader("Sec-Fetch-Storage-Access"_ns, storageAccess);
12082 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !storageAccess.EqualsLiteral("inactive")) {
12083 return;
12084 }
12085 }
12086 }
12087
12088 if (!serializedOrigin.EqualsLiteral("null")) {
12089 // Step 4.1. (Implemented by ReferrerInfo::ShouldSetNullOriginHeader)
12090 if (ReferrerInfo::ShouldSetNullOriginHeader(this, uri)) {
12091 serializedOrigin.AssignLiteral("null");
12092 } else if (StaticPrefs::network_http_sendOriginHeader() == 1) {
12093 // Non-standard: Restrict Origin to same-origin loads if requested by user
12094 nsAutoCString currentOrigin;
12095 nsContentUtils::GetWebExposedOriginSerialization(mURI, currentOrigin);
12096 if (!serializedOrigin.EqualsIgnoreCase(currentOrigin.get())) {
12097 // Origin header suppressed by user setting.
12098 serializedOrigin.AssignLiteral("null");
12099 }
12100 }
12101 }
12102
12103 // Step 4.2. Append (`Origin`, serializedOrigin) to request’s header list.
12104 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", 12105
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12105); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
12105 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", 12105
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12105); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12106}
12107
12108void nsHttpChannel::SetDoNotTrack() {
12109 /**
12110 * 'DoNotTrack' header should be added if 'privacy.donottrackheader.enabled'
12111 * is true.
12112 */
12113 if (StaticPrefs::privacy_donottrackheader_enabled()) {
12114 DebugOnly<nsresult> rv =
12115 mRequestHead.SetHeader(nsHttp::DoNotTrack, "1"_ns, false);
12116 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"
, 12116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 12116); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12117 }
12118}
12119
12120void nsHttpChannel::SetGlobalPrivacyControl() {
12121 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"
, 12121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12121); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12122
12123 if (StaticPrefs::privacy_globalprivacycontrol_enabled() ||
12124 (StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled() &&
12125 NS_UsePrivateBrowsing(this))) {
12126 // Send the header with a value of 1 to indicate opting-out
12127 DebugOnly<nsresult> rv =
12128 mRequestHead.SetHeader(nsHttp::GlobalPrivacyControl, "1"_ns, false);
12129 }
12130}
12131
12132void nsHttpChannel::ReportSystemChannelTelemetry(nsresult status) {
12133 // Use status and httpStatus to determine
12134 // if it was successful, and if we had connectivity / offline in this time
12135 nsAutoCString domain;
12136 mOriginalURI->GetHost(domain);
12137
12138 if (!LoadUsedNetwork()) {
12139 // We're not really interested in any cached requests.
12140 return;
12141 }
12142
12143 if (!StringEndsWith(domain, ".mozilla.org"_ns) &&
12144 !StringEndsWith(domain, ".mozilla.com"_ns) &&
12145 mEssentialDomainCategory.isNothing()) {
12146 return;
12147 }
12148
12149 nsAutoCString label("ok"_ns);
12150 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
12151 if (mCanceled) {
12152 // The request was cancelled.
12153 label = "cancel"_ns;
12154 } else if (NS_IsOffline()) {
12155 // The error occured while all interfaces are offline
12156 label = "offline"_ns;
12157 } else if (!hasConnectivity()) {
12158 // The error occured while the browser didn't have connectivity
12159 label = "connectivity"_ns;
12160 } else if (status == NS_ERROR_UNKNOWN_HOST) {
12161 // The failure was a DNS error
12162 label = "dns"_ns;
12163 } else if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY21) {
12164 // The error was due to TLS
12165 label = "tls_fail"_ns;
12166 } else if (status == NS_ERROR_NET_RESET) {
12167 label = "reset"_ns;
12168 } else if (status == NS_ERROR_NET_TIMEOUT) {
12169 label = "timeout"_ns;
12170 } else if (status == NS_ERROR_CONNECTION_REFUSED) {
12171 label = "refused"_ns;
12172 } else if (status == NS_ERROR_NET_PARTIAL_TRANSFER) {
12173 label = "partial"_ns;
12174 } else {
12175 // Unspecified error. If this bucket is too big we might add other labels.
12176 label = "other"_ns;
12177 }
12178 } else if (mResponseHead && mResponseHead->Status() / 100 != 2) {
12179 // There was no channel error, but the server responded with a non-2XX
12180 // status code.
12181 label = "http_status";
12182 }
12183
12184 // This is the first time failure channel
12185 if (mEssentialDomainCategory.isNothing()) {
12186 auto category = GetEssentialDomainCategory(domain);
12187 switch (category) {
12188 case EssentialDomainCategory::SubAddonsMozillaOrg: {
12189 mozilla::glean::network::system_channel_addonversion_status.Get(label)
12190 .Add(1);
12191 return;
12192 }
12193 case EssentialDomainCategory::AddonsMozillaOrg: {
12194 mozilla::glean::network::system_channel_addon_status.Get(label).Add(1);
12195 return;
12196 }
12197 case EssentialDomainCategory::Aus5MozillaOrg: {
12198 mozilla::glean::network::system_channel_update_status.Get(label).Add(1);
12199 return;
12200 }
12201 case EssentialDomainCategory::RemoteSettings: {
12202 mozilla::glean::network::system_channel_remote_settings_status
12203 .Get(label)
12204 .Add(1);
12205 return;
12206 }
12207 case EssentialDomainCategory::Telemetry: {
12208 mozilla::glean::network::system_channel_telemetry_status.Get(label).Add(
12209 1);
12210 return;
12211 }
12212 default: {
12213 // Not one of the probes we recorded earlier.
12214 mozilla::glean::network::system_channel_other_status.Get(label).Add(1);
12215 return;
12216 }
12217 }
12218 }
12219
12220 // This is a retry.
12221 switch (mEssentialDomainCategory.ref()) {
12222 case EssentialDomainCategory::SubAddonsMozillaOrg: {
12223 mozilla::glean::network::retried_system_channel_addonversion_status
12224 .Get(label)
12225 .Add(1);
12226 return;
12227 }
12228 case EssentialDomainCategory::AddonsMozillaOrg: {
12229 mozilla::glean::network::retried_system_channel_addon_status.Get(label)
12230 .Add(1);
12231 return;
12232 }
12233 case EssentialDomainCategory::Aus5MozillaOrg: {
12234 mozilla::glean::network::retried_system_channel_update_status.Get(label)
12235 .Add(1);
12236 return;
12237 }
12238 case EssentialDomainCategory::RemoteSettings: {
12239 mozilla::glean::network::retried_system_channel_remote_settings_status
12240 .Get(label)
12241 .Add(1);
12242 return;
12243 }
12244 case EssentialDomainCategory::Telemetry: {
12245 mozilla::glean::network::retried_system_channel_telemetry_status
12246 .Get(label)
12247 .Add(1);
12248 return;
12249 }
12250 default: {
12251 // Not one of the probes we recorded earlier.
12252 mozilla::glean::network::retried_system_channel_other_status.Get(label)
12253 .Add(1);
12254 return;
12255 }
12256 }
12257}
12258
12259nsresult nsHttpChannel::TriggerNetwork() {
12260 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"
, 12260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12260); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12261
12262 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)
;
12263
12264 if (mCanceled) {
12265 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)
;
12266 return mStatus;
12267 }
12268
12269 // If a network request has already gone out, there is no point in
12270 // doing this again.
12271 if (mNetworkTriggered) {
12272 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)
;
12273 return NS_OK;
12274 }
12275
12276 mNetworkTriggered = true;
12277
12278 // If we are waiting for a proxy request, that means we can't trigger
12279 // the next step just yet. We need for mConnectionInfo to be non-null
12280 // before we call ContinueConnect. OnProxyAvailable will trigger
12281 // BeginConnect, and Connect will call ContinueConnect even if it's
12282 // for the cache callbacks.
12283 if (mProxyRequest) {
12284 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)
;
12285 mWaitingForProxy = true;
12286 return NS_OK;
12287 }
12288
12289 return ContinueConnect();
12290}
12291
12292nsresult nsHttpChannel::OnSuspendTimeout() {
12293 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"
, 12293); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12293); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12294
12295 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)
;
12296
12297 // If we're still suspended and have a cache entry, enable bypass mode
12298 // This allows any waiting or future listeners to continue
12299 if (mSuspendCount > 0 && mCacheEntry) {
12300 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)
;
12301 mCacheEntry->SetBypassWriterLock(true);
12302 mBypassCacheWriterSet = true;
12303 }
12304
12305 return NS_OK;
12306}
12307
12308nsHttpChannel::TimerCallback::TimerCallback(nsHttpChannel* aChannel)
12309 : mChannel(aChannel) {}
12310
12311NS_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"
, 12311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12311
); __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"
, 12311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12311); __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"
, 12311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12311
); __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"
, 12311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12311); __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"
, 12311); 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; }
12312
12313NS_IMETHODIMPnsresult
12314nsHttpChannel::TimerCallback::GetName(nsACString& aName) {
12315 aName.AssignLiteral("nsHttpChannel");
12316 return NS_OK;
12317}
12318
12319NS_IMETHODIMPnsresult
12320nsHttpChannel::TimerCallback::Notify(nsITimer* aTimer) {
12321 if (aTimer == mChannel->mSuspendTimer) {
12322 return mChannel->OnSuspendTimeout();
12323 }
12324 if (aTimer == mChannel->mCacheWaitTimer) {
12325 return mChannel->OnCacheWaitTimeout();
12326 }
12327 MOZ_CRASH("Unknown timer")do { do { } while (false); MOZ_ReportCrash("" "Unknown timer"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12327
); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown timer" ")"); do
{ MOZ_CrashSequence(__null, 12327); __attribute__((nomerge))
::abort(); } while (false); } while (false)
;
12328
12329 return NS_OK;
12330}
12331
12332void nsHttpChannel::MaybeStartCacheWaitTimer() {
12333 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", 12333
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12333); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12334
12335 uint32_t delay = StaticPrefs::network_cache_entry_wait_timeout_ms();
12336 if (!delay || mCacheWaitTimer || mCacheWaitTimedOut || mNetworkTriggered) {
12337 return;
12338 }
12339
12340 mCacheWaitTimer = NS_NewTimer();
12341 if (mCacheWaitTimer) {
12342 RefPtr<TimerCallback> timerCallback = new TimerCallback(this);
12343 mCacheWaitTimer->InitWithCallback(timerCallback, delay,
12344 nsITimer::TYPE_ONE_SHOT);
12345 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)
12346 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)
;
12347 }
12348}
12349
12350void nsHttpChannel::CancelCacheWaitTimer() {
12351 if (mCacheWaitTimer) {
12352 mCacheWaitTimer->Cancel();
12353 mCacheWaitTimer = nullptr;
12354 }
12355}
12356
12357nsresult nsHttpChannel::OnCacheWaitTimeout() {
12358 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", 12358
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12358); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12359
12360 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)
;
12361 mCacheWaitTimer = nullptr;
12362
12363 // Backstop for a wedged cache entry: if we're still parked waiting for a
12364 // cache entry callback that never arrived (e.g. a writer that was suspended
12365 // or cancelled without ever closing its output stream, so the entry stays
12366 // perpetually "being written"), stop waiting and race to the network so the
12367 // load can make progress instead of hanging forever.
12368 if (!LoadIsPending() || !AwaitingCacheCallbacks()) {
12369 return NS_OK;
12370 }
12371
12372 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)
;
12373 mCacheWaitTimedOut = true;
12374
12375 // Stop treating the outstanding cache open as blocking. We stay registered
12376 // as a callback on the entry, but a late OnCacheEntryCheck or
12377 // OnCacheEntryAvailable will be declined/ignored (see mCacheWaitTimedOut).
12378 StoreWaitForCacheEntry(LoadWaitForCacheEntry() & ~WAIT_FOR_CACHE_ENTRY);
12379
12380 mCacheInputStream.CloseAndRelease();
12381 mAvailableCachedAltDataType.Truncate();
12382 StoreDeliveringAltData(false);
12383 mAltDataLength = -1;
12384
12385 nsresult rv = TriggerNetwork();
12386 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12387 CloseCacheEntry(false);
12388 (void)AsyncAbort(rv);
12389 }
12390 return rv;
12391}
12392
12393bool nsHttpChannel::EligibleForTailing() {
12394 if (!(mClassOfService.Flags() & nsIClassOfService::Tail)) {
12395 return false;
12396 }
12397
12398 if (mClassOfService.Flags() &
12399 (nsIClassOfService::UrgentStart | nsIClassOfService::Leader |
12400 nsIClassOfService::TailForbidden)) {
12401 return false;
12402 }
12403
12404 if (mClassOfService.Flags() & nsIClassOfService::Unblocked &&
12405 !(mClassOfService.Flags() & nsIClassOfService::TailAllowed)) {
12406 return false;
12407 }
12408
12409 if (IsNavigation()) {
12410 return false;
12411 }
12412
12413 return true;
12414}
12415
12416bool nsHttpChannel::WaitingForTailUnblock() {
12417 nsresult rv;
12418
12419 if (!gHttpHandler->IsTailBlockingEnabled()) {
12420 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)
;
12421 return false;
12422 }
12423
12424 if (!EligibleForTailing()) {
12425 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)
;
12426 AddAsNonTailRequest();
12427 return false;
12428 }
12429
12430 if (!EnsureRequestContext()) {
12431 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)
;
12432 return false;
12433 }
12434
12435 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)
12436 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)
;
12437
12438 bool blocked;
12439 rv = mRequestContext->IsContextTailBlocked(this, &blocked);
12440 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12441 return false;
12442 }
12443
12444 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)
;
12445
12446 return blocked;
12447}
12448
12449//-----------------------------------------------------------------------------
12450// nsHttpChannel::nsIRequestTailUnblockCallback
12451//-----------------------------------------------------------------------------
12452
12453// Must be implemented in the leaf class because we don't have
12454// AsyncAbort in HttpBaseChannel.
12455NS_IMETHODIMPnsresult
12456nsHttpChannel::OnTailUnblock(nsresult rv) {
12457 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)
12458 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)
;
12459 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject12460( "nsHttpChannel::OnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
12460 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject12460( "nsHttpChannel::OnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
12461 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", 12461
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 12461); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12462
12463 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
12464 rv = mStatus;
12465 }
12466
12467 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12468 auto callback = mOnTailUnblock;
12469 mOnTailUnblock = nullptr;
12470 rv = (this->*callback)();
12471 }
12472
12473 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12474 CloseCacheEntry(false);
12475 return AsyncAbort(rv);
12476 }
12477
12478 return NS_OK;
12479}
12480
12481void nsHttpChannel::SetWarningReporter(
12482 HttpChannelSecurityWarningReporter* aReporter) {
12483 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)
;
12484 mWarningReporter = aReporter;
12485}
12486
12487HttpChannelSecurityWarningReporter* nsHttpChannel::GetWarningReporter() {
12488 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)
12489 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)
;
12490 return mWarningReporter.get();
12491}
12492
12493// The specification for ORB is currently being written:
12494// https://whatpr.org/fetch/1442.html#orb-algorithm
12495// The `opaque-response-safelist check` is implemented in:
12496// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff`
12497// * `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
12498// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff`
12499// * `OpaqueResponseBlocker::ValidateJavaScript`
12500//
12501// Should only be called by nsMediaSniffer::GetMIMETypeFromContent and
12502// imageLoader::GetMIMETypeFromContent when the content type can be
12503// recognized by these sniffers.
12504void nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck(
12505 SnifferType aType) {
12506 // https://whatpr.org/fetch/1442.html#orb-algorithm
12507 // This method covers steps, 8 and 10.
12508 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", 12508
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 12508); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12509
12510 if (NeedOpaqueResponseAllowedCheckAfterSniff()) {
12511 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"
, 12511); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedOpaqueResponseBlockingPref"
")"); do { MOZ_CrashSequence(__null, 12511); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12512
12513 // If the sniffer type is media and the request comes from a media element,
12514 // we would like to check:
12515 // - Whether the information provided by the media element shows it's an
12516 // initial request.
12517 // - Whether the response's status is either 200 or 206.
12518 //
12519 // If any of the results is false, then we set
12520 // mBlockOpaqueResponseAfterSniff to true and block the response later.
12521 if (aType == SnifferType::Media) {
12522 // Step 8
12523 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"
, 12523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo"
")"); do { MOZ_CrashSequence(__null, 12523); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12524
12525 auto noCorsMediaRequestState = NoCorsMediaRequestState();
12526 if (noCorsMediaRequestState !=
12527 dom::NoCorsMediaRequestState::NotAvailable) {
12528 if (noCorsMediaRequestState != dom::NoCorsMediaRequestState::Initial) {
12529 // Step 8.1
12530 BlockOpaqueResponseAfterSniff(
12531 u"media request after sniffing, but not initial request"_ns,
12532 OpaqueResponseBlockedTelemetryReason::eMediaNotInitial);
12533 return;
12534 }
12535
12536 if (mResponseHead->Status() != 200 && mResponseHead->Status() != 206) {
12537 // Step 8.2
12538 BlockOpaqueResponseAfterSniff(
12539 u"media request's response status is neither 200 nor 206"_ns,
12540 OpaqueResponseBlockedTelemetryReason::eMediaIncorrectResp);
12541 return;
12542 }
12543
12544 // At this point we've checked that the requested resource is media and
12545 // that the sniff passes. Any following requests for this resource
12546 // should be considered to be subsequent.
12547 RecordSubsequentNoCorsRequestState();
12548 }
12549 }
12550
12551 // Step 8.3 if `aType == SnifferType::Media`
12552 // Step 9 can be skipped, only `HTMLMediaElement` ever sets isMediaRequest.
12553 // Step 10 if `aType == SnifferType::Image`
12554 AllowOpaqueResponseAfterSniff();
12555 }
12556}
12557
12558namespace {
12559
12560class CopyNonDefaultHeaderVisitor final : public nsIHttpHeaderVisitor {
12561 nsCOMPtr<nsIHttpChannel> mTarget;
12562
12563 ~CopyNonDefaultHeaderVisitor() = default;
12564
12565 NS_IMETHODvirtual nsresult
12566 VisitHeader(const nsACString& aHeader, const nsACString& aValue) override {
12567 if (aValue.IsEmpty()) {
12568 return mTarget->SetEmptyRequestHeader(aHeader);
12569 }
12570 return mTarget->SetRequestHeader(aHeader, aValue, false /* merge */);
12571 }
12572
12573 public:
12574 explicit CopyNonDefaultHeaderVisitor(nsIHttpChannel* aTarget)
12575 : mTarget(aTarget) {
12576 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"
, 12576); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mTarget"
")"); do { MOZ_CrashSequence(__null, 12576); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12577 }
12578
12579 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:
12580};
12581
12582NS_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"
, 12582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12582
); __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"
, 12582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12582); __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"
, 12582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12582
); __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"
, 12582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12582); __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"
, 12582); 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; }
12583
12584} // anonymous namespace
12585
12586nsresult nsHttpChannel::RedirectToInterceptedChannel() {
12587 nsCOMPtr<nsINetworkInterceptController> controller;
12588 GetCallback(controller);
12589
12590 RefPtr<InterceptedHttpChannel> intercepted =
12591 InterceptedHttpChannel::CreateForInterception(
12592 mChannelCreationTime, mChannelCreationTimestamp, mAsyncOpenTime);
12593
12594 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
12595 CloneLoadInfoForRedirect(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
12596
12597 nsresult rv = intercepted->Init(
Value stored to 'rv' during its initialization is never read
12598 mURI, mCaps, static_cast<nsProxyInfo*>(mProxyInfo.get()),
12599 mProxyResolveFlags, mProxyURI, mChannelId, redirectLoadInfo);
12600
12601 rv = SetupReplacementChannel(mURI, intercepted, true,
12602 nsIChannelEventSink::REDIRECT_INTERNAL);
12603 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"
, 12603); return rv; } } while (false)
;
12604
12605 // Some APIs, like fetch(), allow content to set non-standard headers.
12606 // Normally these APIs are responsible for copying these headers across
12607 // redirects. In the e10s parent-side intercept case, though, we currently
12608 // "hide" the internal redirect to the InterceptedHttpChannel. So the
12609 // fetch() API does not have the opportunity to move headers over.
12610 // Therefore, we do it automatically here.
12611 //
12612 // Once child-side interception is removed and the internal redirect no
12613 // longer needs to be "hidden", then this header copying code can be
12614 // removed.
12615 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
12616 new CopyNonDefaultHeaderVisitor(intercepted);
12617 rv = VisitNonDefaultRequestHeaders(visitor);
12618 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"
, 12618); return rv; } } while (false)
;
12619
12620 mRedirectChannel = intercepted;
12621
12622 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
12623
12624 rv = gHttpHandler->AsyncOnChannelRedirect(
12625 this, intercepted, nsIChannelEventSink::REDIRECT_INTERNAL);
12626
12627 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12628 rv = WaitForRedirectCallback();
12629 }
12630
12631 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12632 AutoRedirectVetoNotifier notifier(this, rv);
12633
12634 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
12635 }
12636
12637 return rv;
12638}
12639
12640void nsHttpChannel::ReEvaluateReferrerAfterTrackingStatusIsKnown() {
12641 nsCOMPtr<nsICookieJarSettings> cjs;
12642 if (mLoadInfo) {
12643 (void)mLoadInfo->GetCookieJarSettings(getter_AddRefs(cjs));
12644 }
12645 if (!cjs) {
12646 cjs = net::CookieJarSettings::Create(mLoadInfo->GetLoadingPrincipal());
12647 }
12648 if (cjs->GetRejectThirdPartyContexts()) {
12649 bool isPrivate = mLoadInfo->GetOriginAttributes().IsPrivateBrowsing();
12650 // If our referrer has been set before, and our referrer policy is unset
12651 // (default policy) if we thought the channel wasn't a third-party
12652 // tracking channel, we may need to set our referrer with referrer policy
12653 // once again to ensure our defaults properly take effect now.
12654 if (mReferrerInfo) {
12655 ReferrerInfo* referrerInfo =
12656 static_cast<ReferrerInfo*>(mReferrerInfo.get());
12657
12658 if (referrerInfo->IsPolicyOverrided() &&
12659 referrerInfo->ReferrerPolicy() ==
12660 ReferrerInfo::GetDefaultReferrerPolicy(nullptr, nullptr,
12661 isPrivate)) {
12662 nsCOMPtr<nsIReferrerInfo> newReferrerInfo =
12663 referrerInfo->CloneWithNewPolicy(
12664 ReferrerInfo::GetDefaultReferrerPolicy(this, mURI, isPrivate));
12665 // The arguments passed to SetReferrerInfoInternal here should mirror
12666 // the arguments passed in
12667 // HttpChannelChild::RecvOverrideReferrerInfoDuringBeginConnect().
12668 SetReferrerInfoInternal(newReferrerInfo, false, true, true);
12669
12670 nsCOMPtr<nsIParentChannel> parentChannel;
12671 NS_QueryNotificationCallbacks(this, parentChannel);
12672 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
12673 if (httpParent) {
12674 httpParent->OverrideReferrerInfoDuringBeginConnect(newReferrerInfo);
12675 }
12676 }
12677 }
12678 }
12679}
12680
12681namespace {
12682
12683// Also acts as the only notification callbacks of the revalidating channel, so
12684// that none of its notifications reach the consumer of the original channel.
12685class BackgroundRevalidatingListener : public nsIStreamListener,
12686 public nsIInterfaceRequestor,
12687 public nsIChannelEventSink {
12688 public:
12689 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:
12690 NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream
*aInputStream, uint64_t aOffset, uint32_t aCount) override;
12691 NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override
; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult
aStatusCode) override;
12692 NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * *
result) override;
12693 NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel
, nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback
*callback) override;
12694
12695 private:
12696 virtual ~BackgroundRevalidatingListener() = default;
12697};
12698
12699NS_IMETHODIMPnsresult
12700BackgroundRevalidatingListener::OnStartRequest(nsIRequest* request) {
12701 return NS_OK;
12702}
12703
12704NS_IMETHODIMPnsresult
12705BackgroundRevalidatingListener::OnDataAvailable(nsIRequest* request,
12706 nsIInputStream* input,
12707 uint64_t offset,
12708 uint32_t count) {
12709 uint32_t bytesRead = 0;
12710 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &bytesRead);
12711}
12712
12713NS_IMETHODIMPnsresult
12714BackgroundRevalidatingListener::OnStopRequest(nsIRequest* request,
12715 nsresult status) {
12716 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
12717 return status;
12718 }
12719
12720 nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(request));
12721 if (gHttpHandler) {
12722 gHttpHandler->OnBackgroundRevalidation(channel);
12723 }
12724 return NS_OK;
12725}
12726
12727NS_IMETHODIMPnsresult
12728BackgroundRevalidatingListener::GetInterface(const nsIID& aIID,
12729 void** aResult) {
12730 if (aIID.Equals(NS_GET_IID(nsIChannelEventSink)(nsIChannelEventSink::kIID))) {
12731 return QueryInterface(aIID, aResult);
12732 }
12733 return NS_ERROR_NO_INTERFACE;
12734}
12735
12736// The redirect response itself revalidates the cache entry, there is no need
12737// to follow it.
12738NS_IMETHODIMPnsresult
12739BackgroundRevalidatingListener::AsyncOnChannelRedirect(
12740 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
12741 nsIAsyncVerifyRedirectCallback* aCallback) {
12742 LOG(("BackgroundRevalidatingListener::AsyncOnChannelRedirect %p vetoing",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "BackgroundRevalidatingListener::AsyncOnChannelRedirect %p vetoing"
, aOldChannel); } } while (0)
12743 aOldChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "BackgroundRevalidatingListener::AsyncOnChannelRedirect %p vetoing"
, aOldChannel); } } while (0)
;
12744 return NS_BINDING_ABORTED;
12745}
12746
12747NS_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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12749
); __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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12749); __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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12749
); __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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12749); __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", 12749
); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<BackgroundRevalidatingListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((BackgroundRevalidatingListener*)0x1000)) - reinterpret_cast
<char*>((BackgroundRevalidatingListener*)0x1000))}, {&
mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIStreamListener*>((
BackgroundRevalidatingListener*)0x1000))) - reinterpret_cast<
char*>((BackgroundRevalidatingListener*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
12748 nsIRequestObserver, nsIInterfaceRequestor,MozExternalRefCountType BackgroundRevalidatingListener::AddRef
(void) { static_assert(!std::is_destructible_v<BackgroundRevalidatingListener
>, "Reference-counted class " "BackgroundRevalidatingListener"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12749
); __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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12749); __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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12749
); __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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12749); __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", 12749
); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<BackgroundRevalidatingListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((BackgroundRevalidatingListener*)0x1000)) - reinterpret_cast
<char*>((BackgroundRevalidatingListener*)0x1000))}, {&
mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIStreamListener*>((
BackgroundRevalidatingListener*)0x1000))) - reinterpret_cast<
char*>((BackgroundRevalidatingListener*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
12749 nsIChannelEventSink)MozExternalRefCountType BackgroundRevalidatingListener::AddRef
(void) { static_assert(!std::is_destructible_v<BackgroundRevalidatingListener
>, "Reference-counted class " "BackgroundRevalidatingListener"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12749
); __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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12749); __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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12749
); __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"
, 12749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12749); __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", 12749
); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<BackgroundRevalidatingListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((BackgroundRevalidatingListener*)0x1000)) - reinterpret_cast
<char*>((BackgroundRevalidatingListener*)0x1000))}, {&
mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIStreamListener*>((
BackgroundRevalidatingListener*)0x1000))) - reinterpret_cast<
char*>((BackgroundRevalidatingListener*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
12750
12751} // namespace
12752
12753void nsHttpChannel::PerformBackgroundCacheRevalidation() {
12754 if (!StaticPrefs::network_http_stale_while_revalidate_enabled()) {
12755 return;
12756 }
12757
12758 // This is a channel doing a revalidation. It shouldn't do it again.
12759 if (mStaleRevalidation) {
12760 return;
12761 }
12762
12763 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)
;
12764
12765 (void)NS_DispatchToMainThreadQueue(
12766 NewIdleRunnableMethod(
12767 "nsHttpChannel::PerformBackgroundCacheRevalidation", this,
12768 &nsHttpChannel::PerformBackgroundCacheRevalidationNow),
12769 EventQueuePriority::Idle);
12770}
12771
12772void nsHttpChannel::PerformBackgroundCacheRevalidationNow() {
12773 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)
;
12774
12775 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", 12775
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12775); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12776
12777 nsresult rv;
12778
12779 nsLoadFlags loadFlags = mLoadFlags | LOAD_ONLY_IF_MODIFIED | VALIDATE_ALWAYS |
12780 LOAD_BACKGROUND | LOAD_BYPASS_SERVICE_WORKER;
12781
12782 RefPtr<BackgroundRevalidatingListener> listener =
12783 new BackgroundRevalidatingListener();
12784
12785 nsCOMPtr<nsIPrincipal> principal;
12786 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
12787 this, getter_AddRefs(principal));
12788 nsCOMPtr<nsILoadGroup> loadGroup;
12789 rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), principal);
12790 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12791 LOG((" failed to create the load group, rv=0x%08x",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " failed to create the load group, rv=0x%08x", static_cast
<uint32_t>(rv)); } } while (0)
12792 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " failed to create the load group, rv=0x%08x", static_cast
<uint32_t>(rv)); } } while (0)
;
12793 return;
12794 }
12795
12796 // XXX(valentin): Preserving the old load info means mInitialSecurityCheckDone
12797 // will be true. Using CloneForNewRequest would be closer to the spec, but
12798 // it would mean redoing previous checks.
12799 nsCOMPtr<nsILoadInfo> loadInfo =
12800 static_cast<mozilla::net::LoadInfo*>(mLoadInfo.get())->Clone();
12801
12802 nsCOMPtr<nsIChannel> validatingChannel;
12803 rv = NS_NewChannelInternal(getter_AddRefs(validatingChannel), mURI, loadInfo,
12804 nullptr /* performance storage */, loadGroup,
12805 listener, loadFlags);
12806 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12807 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)
12808 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)
;
12809 return;
12810 }
12811
12812 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(validatingChannel));
12813 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"
, 12813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpChannel"
")"); do { MOZ_CrashSequence(__null, 12813); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12814
12815 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
12816 new CopyNonDefaultHeaderVisitor(httpChannel);
12817 rv = VisitNonDefaultRequestHeaders(visitor);
12818 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12819 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)
12820 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)
;
12821 return;
12822 }
12823
12824 nsCOMPtr<nsISupportsPriority> priority(do_QueryInterface(validatingChannel));
12825 if (priority) {
12826 priority->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
12827 }
12828
12829 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(validatingChannel));
12830 if (cos) {
12831 cos->AddClassFlags(nsIClassOfService::Tail);
12832 }
12833
12834 RefPtr<nsHttpChannel> httpChan = do_QueryObject(validatingChannel);
12835 if (httpChan) {
12836 httpChan->mStaleRevalidation = true;
12837 }
12838
12839 rv = validatingChannel->AsyncOpen(listener);
12840 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12841 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)
;
12842 return;
12843 }
12844
12845 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)
12846 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)
;
12847}
12848
12849NS_IMETHODIMPnsresult
12850nsHttpChannel::SetEarlyHintObserver(nsIEarlyHintObserver* aObserver) {
12851 mEarlyHintObserver = aObserver;
12852 return NS_OK;
12853}
12854
12855NS_IMETHODIMPnsresult
12856nsHttpChannel::EarlyHint(const nsACString& aLinkHeader,
12857 const nsACString& aReferrerPolicy,
12858 const nsACString& aCspHeader) {
12859 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)
;
12860
12861 if (nsCOMPtr<nsIEarlyHintObserver> obs = mEarlyHintObserver) {
12862 if (nsContentUtils::ComputeIsSecureContext(this)) {
12863 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)
;
12864 obs->EarlyHint(aLinkHeader, aReferrerPolicy, aCspHeader);
12865 }
12866 }
12867 return NS_OK;
12868}
12869
12870NS_IMETHODIMPnsresult nsHttpChannel::SetResponseOverride(
12871 nsIReplacedHttpResponse* aReplacedHttpResponse) {
12872 mOverrideResponse = new nsMainThreadPtrHolder<nsIReplacedHttpResponse>(
12873 "nsIReplacedHttpResponse", aReplacedHttpResponse);
12874
12875 if (LoadRequireCORSPreflight()) {
12876 // Bug 1986615, Bug 1940738, responses provided via setResponseOverride will
12877 // be handled before the preflight can be sent, flag it as done.
12878 StoreIsCorsPreflightDone(true);
12879 }
12880
12881 return NS_OK;
12882}
12883
12884NS_IMETHODIMPnsresult nsHttpChannel::SetResponseStatus(uint32_t aStatus,
12885 const nsACString& aStatusText) {
12886 if (!mResponseHead) {
12887 return NS_ERROR_NOT_AVAILABLE;
12888 }
12889
12890 nsAutoCString statusText(aStatusText);
12891 nsAutoCString protocolVersion(
12892 nsHttp::GetProtocolVersion(mResponseHead->Version()));
12893 ToUpperCase(protocolVersion);
12894
12895 nsPrintfCString line("%s %u %s", protocolVersion.get(), aStatus,
12896 statusText.get());
12897
12898 return mResponseHead->ParseStatusLine(line);
12899}
12900
12901NS_IMETHODIMPnsresult nsHttpChannel::SetWebTransportSessionEventListener(
12902 WebTransportSessionEventListener* aListener) {
12903 mWebTransportSessionEventListener = aListener;
12904 return NS_OK;
12905}
12906
12907already_AddRefed<WebTransportSessionEventListener>
12908nsHttpChannel::GetWebTransportSessionEventListener() {
12909 RefPtr<WebTransportSessionEventListener> wt =
12910 mWebTransportSessionEventListener;
12911 return wt.forget();
12912}
12913
12914NS_IMETHODIMPnsresult nsHttpChannel::GetLastTransportStatus(
12915 nsresult* aLastTransportStatus) {
12916 *aLastTransportStatus = mLastTransportStatus;
12917 return NS_OK;
12918}
12919
12920NS_IMETHODIMPnsresult
12921nsHttpChannel::GetCacheDisposition(CacheDisposition* aDisposition) {
12922 if (!aDisposition) {
12923 return NS_ERROR_INVALID_ARG;
12924 }
12925 *aDisposition = mCacheDisposition;
12926 return NS_OK;
12927}
12928
12929} // namespace net
12930} // namespace mozilla