Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp
Warning:line 4980, column 3
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_protocol_http4.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/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 /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/cookie -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/socket/neqo_glue -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/url-classifier -I /var/lib/jenkins/workspace/firefox-scan-build/extensions/auth -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -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-deprecated-this-capture -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 -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 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c++ Unified_cpp_protocol_http4.cpp
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim:set expandtab ts=4 sw=2 sts=2 cin: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7// HttpLog.h should generally be included first
8#include "HttpLog.h"
9
10#include <inttypes.h>
11
12#include "mozilla/ScopeExit.h"
13#include "mozilla/Sprintf.h"
14#include "mozilla/dom/nsCSPContext.h"
15#include "mozilla/glean/GleanMetrics.h"
16#include "mozilla/StoragePrincipalHelper.h"
17
18#include "nsCOMPtr.h"
19#include "nsContentSecurityUtils.h"
20#include "nsHttp.h"
21#include "nsHttpChannel.h"
22#include "nsHttpChannelAuthProvider.h"
23#include "nsHttpHandler.h"
24#include "nsIStreamConverter.h"
25#include "nsString.h"
26#include "nsICacheStorageService.h"
27#include "nsICacheStorage.h"
28#include "nsICacheEntry.h"
29#include "nsICryptoHash.h"
30#include "nsIEffectiveTLDService.h"
31#include "nsIHttpHeaderVisitor.h"
32#include "nsINetworkInterceptController.h"
33#include "nsIStringBundle.h"
34#include "nsIStreamListenerTee.h"
35#include "nsISeekableStream.h"
36#include "nsIProtocolProxyService2.h"
37#include "nsIURLQueryStringStripper.h"
38#include "nsIWebTransport.h"
39#include "nsCRT.h"
40#include "nsMimeTypes.h"
41#include "nsNetCID.h"
42#include "nsNetUtil.h"
43#include "nsIStreamTransportService.h"
44#include "prnetdb.h"
45#include "nsEscape.h"
46#include "nsComponentManagerUtils.h"
47#include "nsStreamUtils.h"
48#include "nsIOService.h"
49#include "nsDNSPrefetch.h"
50#include "nsChannelClassifier.h"
51#include "nsIRedirectResultListener.h"
52#include "mozilla/TimeStamp.h"
53#include "nsError.h"
54#include "nsPrintfCString.h"
55#include "nsAlgorithm.h"
56#include "nsQueryObject.h"
57#include "nsThreadUtils.h"
58#include "nsIConsoleService.h"
59#include "nsINetworkErrorLogging.h"
60#include "mozilla/AntiTrackingRedirectHeuristic.h"
61#include "mozilla/AntiTrackingUtils.h"
62#include "mozilla/Attributes.h"
63#include "mozilla/BasePrincipal.h"
64#include "mozilla/DebugOnly.h"
65#include "mozilla/PerfStats.h"
66#include "mozilla/ProfilerLabels.h"
67#include "mozilla/Components.h"
68#include "mozilla/StaticPrefs_network.h"
69#include "mozilla/StaticPrefs_privacy.h"
70#include "mozilla/StaticPrefs_security.h"
71#include "sslt.h"
72#include "nsCharSeparatedTokenizer.h"
73#include "nsContentUtils.h"
74#include "nsContentSecurityManager.h"
75#include "nsIClassOfService.h"
76#include "nsIPrincipal.h"
77#include "nsIScriptError.h"
78#include "nsIScriptSecurityManager.h"
79#include "nsITransportSecurityInfo.h"
80#include "nsIWebProgressListener.h"
81#include "LoadContextInfo.h"
82#include "netCore.h"
83#include "nsHttpTransaction.h"
84#include "nsICancelable.h"
85#include "nsIHttpChannelInternal.h"
86#include "nsIPrompt.h"
87#include "nsInputStreamPump.h"
88#include "nsURLHelper.h"
89#include "nsISocketTransport.h"
90#include "nsIStreamConverterService.h"
91#include "nsISiteSecurityService.h"
92#include "nsString.h"
93#include "nsStringStream.h"
94#include "mozilla/dom/PerformanceStorage.h"
95#include "mozilla/dom/ReferrerInfo.h"
96#include "mozilla/Telemetry.h"
97#include "AlternateServices.h"
98#include "NetworkMarker.h"
99#include "nsIHttpPushListener.h"
100#include "nsIDNSRecord.h"
101#include "mozilla/dom/Document.h"
102#include "nsICompressConvStats.h"
103#include "nsCORSListenerProxy.h"
104#include "nsISocketProvider.h"
105#include "mozilla/extensions/StreamFilterParent.h"
106#include "mozilla/net/Predictor.h"
107#include "mozilla/MathAlgorithms.h"
108#include "mozilla/NullPrincipal.h"
109#include "CacheControlParser.h"
110#include "nsMixedContentBlocker.h"
111#include "CacheStorageService.h"
112#include "HttpChannelParent.h"
113#include "HttpTransactionParent.h"
114#include "ThirdPartyUtil.h"
115#include "InterceptedHttpChannel.h"
116#include "../../cache2/CacheFileUtils.h"
117#include "nsINetworkLinkService.h"
118#include "mozilla/ContentBlockingAllowList.h"
119#include "mozilla/dom/ServiceWorkerUtils.h"
120#include "mozilla/dom/nsHTTPSOnlyStreamListener.h"
121#include "mozilla/dom/nsHTTPSOnlyUtils.h"
122#include "mozilla/net/AsyncUrlChannelClassifier.h"
123#include "mozilla/net/CookieJarSettings.h"
124#include "mozilla/net/NeckoChannelParams.h"
125#include "mozilla/net/OpaqueResponseUtils.h"
126#include "mozilla/net/UrlClassifierFeatureFactory.h"
127#include "HttpTrafficAnalyzer.h"
128#include "mozilla/net/SocketProcessParent.h"
129#include "mozilla/dom/SecFetch.h"
130#include "mozilla/net/TRRService.h"
131#include "nsUnknownDecoder.h"
132#ifdef XP_WIN
133# include "HttpWinUtils.h"
134#endif
135#ifdef XP_MACOSX
136# include "MicrosoftEntraSSOUtils.h"
137#endif
138#ifdef FUZZING
139# include "mozilla/StaticPrefs_fuzzing.h"
140#endif
141
142namespace mozilla {
143
144using namespace dom;
145
146namespace net {
147
148namespace {
149
150// True if the local cache should be bypassed when processing a request.
151#define BYPASS_LOCAL_CACHE(loadFlags, isPreferCacheLoadOverBypass)((loadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((loadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (isPreferCacheLoadOverBypass)))
\
152 ((loadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | \
153 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE) && \
154 !(((loadFlags) & nsIRequest::LOAD_FROM_CACHE) && \
155 (isPreferCacheLoadOverBypass)))
156
157#define RECOVER_FROM_CACHE_FILE_ERROR(result)((result) == NS_ERROR_FILE_NOT_FOUND || (result) == NS_ERROR_FILE_CORRUPTED
|| (result) == NS_ERROR_OUT_OF_MEMORY)
\
158 ((result) == NS_ERROR_FILE_NOT_FOUND || \
159 (result) == NS_ERROR_FILE_CORRUPTED || (result) == NS_ERROR_OUT_OF_MEMORY)
160
161#define WRONG_RACING_RESPONSE_SOURCE(req)(mRaceCacheWithNetwork && (((mFirstResponseSource == RESPONSE_FROM_CACHE
) && ((req) != mCachePump)) || ((mFirstResponseSource
== RESPONSE_FROM_NETWORK) && ((req) != mTransactionPump
))))
\
162 (mRaceCacheWithNetwork && \
163 (((mFirstResponseSource == RESPONSE_FROM_CACHE) && \
164 ((req) != mCachePump)) || \
165 ((mFirstResponseSource == RESPONSE_FROM_NETWORK) && \
166 ((req) != mTransactionPump))))
167
168static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID)const nsCID kStreamListenerTeeCID = { 0x831f8f13, 0x7aa8, 0x485f
, { 0xb0, 0x2e, 0x77, 0xc8, 0x81, 0xcc, 0x57, 0x73 } }
;
169
170enum ChannelDisposition {
171 kHttpCanceled = 0,
172 kHttpDisk = 1,
173 kHttpNetOK = 2,
174 kHttpNetEarlyFail = 3,
175 kHttpNetLateFail = 4,
176 kHttpsCanceled = 8,
177 kHttpsDisk = 9,
178 kHttpsNetOK = 10,
179 kHttpsNetEarlyFail = 11,
180 kHttpsNetLateFail = 12
181};
182
183void AccumulateCacheHitTelemetry(CacheDisposition hitOrMiss,
184 nsIChannel* aChannel) {
185 nsCString key("UNKNOWN");
186
187 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
188
189 nsAutoCString contentType;
190 if (NS_SUCCEEDED(aChannel->GetContentType(contentType))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aChannel->GetContentType
(contentType))), 1)))
) {
191 if (nsContentUtils::IsJavascriptMIMEType(
192 NS_ConvertUTF8toUTF16(contentType))) {
193 key.AssignLiteral("JAVASCRIPT");
194 } else if (StringBeginsWith(contentType, "text/css"_ns) ||
195 (loadInfo && loadInfo->GetExternalContentPolicyType() ==
196 ExtContentPolicy::TYPE_STYLESHEET)) {
197 key.AssignLiteral("STYLESHEET");
198 } else if (StringBeginsWith(contentType, "application/wasm"_ns)) {
199 key.AssignLiteral("WASM");
200 } else if (StringBeginsWith(contentType, "image/"_ns)) {
201 key.AssignLiteral("IMAGE");
202 } else if (StringBeginsWith(contentType, "video/"_ns)) {
203 key.AssignLiteral("MEDIA");
204 } else if (StringBeginsWith(contentType, "audio/"_ns)) {
205 key.AssignLiteral("MEDIA");
206 } else if (!StringBeginsWith(contentType,
207 nsLiteralCString(UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type"))) {
208 key.AssignLiteral("OTHER");
209 }
210 }
211
212 Telemetry::LABELS_HTTP_CACHE_DISPOSITION_3 label =
213 Telemetry::LABELS_HTTP_CACHE_DISPOSITION_3::Unresolved;
214 switch (hitOrMiss) {
215 case kCacheUnresolved:
216 label = Telemetry::LABELS_HTTP_CACHE_DISPOSITION_3::Unresolved;
217 break;
218 case kCacheHit:
219 label = Telemetry::LABELS_HTTP_CACHE_DISPOSITION_3::Hit;
220 break;
221 case kCacheHitViaReval:
222 label = Telemetry::LABELS_HTTP_CACHE_DISPOSITION_3::HitViaReval;
223 break;
224 case kCacheMissedViaReval:
225 label = Telemetry::LABELS_HTTP_CACHE_DISPOSITION_3::MissedViaReval;
226 break;
227 case kCacheMissed:
228 label = Telemetry::LABELS_HTTP_CACHE_DISPOSITION_3::Missed;
229 break;
230 case kCacheUnknown:
231 label = Telemetry::LABELS_HTTP_CACHE_DISPOSITION_3::Unknown;
232 break;
233 }
234
235 Telemetry::AccumulateCategoricalKeyed(key, label);
236 Telemetry::AccumulateCategoricalKeyed("ALL"_ns, label);
237}
238
239// Computes and returns a SHA1 hash of the input buffer. The input buffer
240// must be a null-terminated string.
241nsresult Hash(const char* buf, nsACString& hash) {
242 nsresult rv;
243
244 nsCOMPtr<nsICryptoHash> hasher =
245 do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID"@mozilla.org/security/hash;1", &rv);
246 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 246); return rv; } } while (false)
;
247
248 rv = hasher->Init(nsICryptoHash::SHA1);
249 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 249); return rv; } } while (false)
;
250
251 rv = hasher->Update(reinterpret_cast<unsigned const char*>(buf), strlen(buf));
252 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 252); return rv; } } while (false)
;
253
254 rv = hasher->Finish(true, hash);
255 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 255); return rv; } } while (false)
;
256
257 return NS_OK;
258}
259
260} // unnamed namespace
261
262// We only treat 3xx responses as redirects if they have a Location header and
263// the status code is in a whitelist.
264bool nsHttpChannel::WillRedirect(const nsHttpResponseHead& response) {
265 return IsRedirectStatus(response.Status()) &&
266 response.HasHeader(nsHttp::Location);
267}
268
269nsresult StoreAuthorizationMetaData(nsICacheEntry* entry,
270 nsHttpRequestHead* requestHead);
271
272class MOZ_STACK_CLASS AutoRedirectVetoNotifier {
273 public:
274 explicit AutoRedirectVetoNotifier(nsHttpChannel* channel, nsresult& aRv)
275 : mChannel(channel), mRv(aRv) {
276 if (mChannel->LoadHasAutoRedirectVetoNotifier()) {
277 MOZ_CRASH("Nested AutoRedirectVetoNotifier on the stack")do { do { } while (false); MOZ_ReportCrash("" "Nested AutoRedirectVetoNotifier on the stack"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 277); AnnotateMozCrashReason("MOZ_CRASH(" "Nested AutoRedirectVetoNotifier on the stack"
")"); do { *((volatile int*)__null) = 277; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
278 mChannel = nullptr;
279 return;
280 }
281
282 mChannel->StoreHasAutoRedirectVetoNotifier(true);
283 }
284 ~AutoRedirectVetoNotifier() { ReportRedirectResult(mRv); }
285 void RedirectSucceeded() { ReportRedirectResult(NS_OK); }
286
287 private:
288 nsHttpChannel* mChannel;
289 bool mCalledReport = false;
290 nsresult& mRv;
291 void ReportRedirectResult(nsresult aRv);
292};
293
294void AutoRedirectVetoNotifier::ReportRedirectResult(nsresult aRv) {
295 if (!mChannel) return;
296
297 if (mCalledReport) {
298 return;
299 }
300 mCalledReport = true;
301
302 mChannel->mRedirectChannel = nullptr;
303
304 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))) {
305 mChannel->RemoveAsNonTailRequest();
306 }
307
308 nsCOMPtr<nsIRedirectResultListener> vetoHook;
309 NS_QueryNotificationCallbacks(mChannel, NS_GET_IID(nsIRedirectResultListener)(nsIRedirectResultListener::COMTypeInfo<nsIRedirectResultListener
, void>::kIID)
,
310 getter_AddRefs(vetoHook));
311
312 nsHttpChannel* channel = mChannel;
313 mChannel = nullptr;
314
315 if (vetoHook) vetoHook->OnRedirectResult(aRv);
316
317 // Drop after the notification
318 channel->StoreHasAutoRedirectVetoNotifier(false);
319}
320
321//-----------------------------------------------------------------------------
322// nsHttpChannel <public>
323//-----------------------------------------------------------------------------
324
325nsHttpChannel::nsHttpChannel() : HttpAsyncAborter<nsHttpChannel>(this) {
326 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)
327 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)
;
328 mChannelCreationTime = PR_Now();
329 mChannelCreationTimestamp = TimeStamp::Now();
330}
331
332nsHttpChannel::~nsHttpChannel() {
333 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)
334 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)
;
335
336 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
337 nsCString webExtension;
338 this->GetPropertyAsACString(u"cancelledByExtension"_ns, webExtension);
339 if (!webExtension.IsEmpty()) {
340 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)
341 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)
;
342 }
343 }
344
345 if (mAuthProvider) {
346 DebugOnly<nsresult> rv = mAuthProvider->Disconnect(NS_ERROR_ABORT);
347 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 347; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
348 }
349
350 ReleaseMainThreadOnlyReferences();
351 if (gHttpHandler) {
352 gHttpHandler->RemoveHttpChannel(mChannelId);
353 }
354}
355
356void nsHttpChannel::ReleaseMainThreadOnlyReferences() {
357 if (NS_IsMainThread()) {
358 // Already on main thread, let dtor to
359 // take care of releasing references
360 return;
361 }
362
363 nsTArray<nsCOMPtr<nsISupports>> arrayToRelease;
364 arrayToRelease.AppendElement(mAuthProvider.forget());
365 arrayToRelease.AppendElement(mRedirectChannel.forget());
366 arrayToRelease.AppendElement(mPreflightChannel.forget());
367 arrayToRelease.AppendElement(mDNSPrefetch.forget());
368
369 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mEarlyHintObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mEarlyHintObserver))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mEarlyHintObserver"
" (" "Early hint observer should have been released in ReleaseListeners()"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 371); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mEarlyHintObserver"
") (" "Early hint observer should have been released in ReleaseListeners()"
")"); do { *((volatile int*)__null) = 371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
370 !mEarlyHintObserver,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mEarlyHintObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mEarlyHintObserver))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mEarlyHintObserver"
" (" "Early hint observer should have been released in ReleaseListeners()"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 371); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mEarlyHintObserver"
") (" "Early hint observer should have been released in ReleaseListeners()"
")"); do { *((volatile int*)__null) = 371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
371 "Early hint observer should have been released in ReleaseListeners()")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mEarlyHintObserver)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mEarlyHintObserver))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mEarlyHintObserver"
" (" "Early hint observer should have been released in ReleaseListeners()"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 371); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mEarlyHintObserver"
") (" "Early hint observer should have been released in ReleaseListeners()"
")"); do { *((volatile int*)__null) = 371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
372 arrayToRelease.AppendElement(mEarlyHintObserver.forget());
373 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mChannelClassifier)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mChannelClassifier))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mChannelClassifier"
" (" "Channel classifier should have been released in ReleaseListeners()"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 375); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mChannelClassifier"
") (" "Channel classifier should have been released in ReleaseListeners()"
")"); do { *((volatile int*)__null) = 375; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
374 !mChannelClassifier,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mChannelClassifier)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mChannelClassifier))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mChannelClassifier"
" (" "Channel classifier should have been released in ReleaseListeners()"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 375); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mChannelClassifier"
") (" "Channel classifier should have been released in ReleaseListeners()"
")"); do { *((volatile int*)__null) = 375; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
375 "Channel classifier should have been released in ReleaseListeners()")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mChannelClassifier)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mChannelClassifier))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mChannelClassifier"
" (" "Channel classifier should have been released in ReleaseListeners()"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 375); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mChannelClassifier"
") (" "Channel classifier should have been released in ReleaseListeners()"
")"); do { *((volatile int*)__null) = 375; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
376 arrayToRelease.AppendElement(
377 mChannelClassifier.forget().downcast<nsIURIClassifierCallback>());
378 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mWarningReporter)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mWarningReporter))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mWarningReporter"
" (" "Warning reporter should have been released in ReleaseListeners()"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 380); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mWarningReporter"
") (" "Warning reporter should have been released in ReleaseListeners()"
")"); do { *((volatile int*)__null) = 380; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
379 !mWarningReporter,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mWarningReporter)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mWarningReporter))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mWarningReporter"
" (" "Warning reporter should have been released in ReleaseListeners()"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 380); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mWarningReporter"
") (" "Warning reporter should have been released in ReleaseListeners()"
")"); do { *((volatile int*)__null) = 380; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
380 "Warning reporter should have been released in ReleaseListeners()")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mWarningReporter)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mWarningReporter))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mWarningReporter"
" (" "Warning reporter should have been released in ReleaseListeners()"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 380); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mWarningReporter"
") (" "Warning reporter should have been released in ReleaseListeners()"
")"); do { *((volatile int*)__null) = 380; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
381 arrayToRelease.AppendElement(mWarningReporter.forget());
382
383 NS_DispatchToMainThread(new ProxyReleaseRunnable(std::move(arrayToRelease)));
384}
385
386nsresult nsHttpChannel::Init(nsIURI* uri, uint32_t caps, nsProxyInfo* proxyInfo,
387 uint32_t proxyResolveFlags, nsIURI* proxyURI,
388 uint64_t channelId,
389 ExtContentPolicyType aContentPolicyType,
390 nsILoadInfo* aLoadInfo) {
391 nsresult rv =
392 HttpBaseChannel::Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI,
393 channelId, aContentPolicyType, aLoadInfo);
394 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
395
396 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)
;
397
398 return rv;
399}
400
401nsresult nsHttpChannel::AddSecurityMessage(const nsAString& aMessageTag,
402 const nsAString& aMessageCategory) {
403 if (mWarningReporter) {
404 return mWarningReporter->ReportSecurityMessage(aMessageTag,
405 aMessageCategory);
406 }
407 return HttpBaseChannel::AddSecurityMessage(aMessageTag, aMessageCategory);
408}
409
410NS_IMETHODIMPnsresult
411nsHttpChannel::LogBlockedCORSRequest(const nsAString& aMessage,
412 const nsACString& aCategory,
413 bool aIsWarning) {
414 if (mWarningReporter) {
415 return mWarningReporter->LogBlockedCORSRequest(aMessage, aCategory,
416 aIsWarning);
417 }
418 return NS_ERROR_UNEXPECTED;
419}
420
421NS_IMETHODIMPnsresult
422nsHttpChannel::LogMimeTypeMismatch(const nsACString& aMessageName,
423 bool aWarning, const nsAString& aURL,
424 const nsAString& aContentType) {
425 if (mWarningReporter) {
426 return mWarningReporter->LogMimeTypeMismatch(aMessageName, aWarning, aURL,
427 aContentType);
428 }
429 return NS_ERROR_UNEXPECTED;
430}
431
432//-----------------------------------------------------------------------------
433// nsHttpChannel <private>
434//-----------------------------------------------------------------------------
435
436nsresult nsHttpChannel::PrepareToConnect() {
437 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)
;
438
439 // notify "http-on-modify-request-before-cookies" observers
440 gHttpHandler->OnModifyRequestBeforeCookies(this);
441
442 AddCookiesToRequest();
443
444#if defined(XP_WIN) || defined(XP_MACOSX)
445
446 auto prefEnabledForCurrentContainer = [&]() {
447 uint32_t containerId = mLoadInfo->GetOriginAttributes().mUserContextId;
448 // Make sure that the default container ID is 0
449 static_assert(nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID == 0);
450
451 nsAutoCString prefName;
452# ifdef XP_WIN
453 prefName = nsPrintfCString("network.http.windows-sso.container-enabled.%u",
454 containerId);
455# endif
456
457# ifdef XP_MACOSX
458 prefName = nsPrintfCString(
459 "network.http.microsoft-entra-sso.container-enabled.%u", containerId);
460# endif
461
462 bool enabled = false;
463 Preferences::GetBool(prefName.get(), &enabled);
464
465 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)
;
466
467 return enabled;
468 };
469
470#endif // defined(XP_WIN) || defined(XP_MACOSX)
471
472#ifdef XP_WIN
473
474 // If Windows 10 SSO is enabled, we potentially add auth
475 // information to secure top level loads (DOCUMENTs) and iframes
476 // (SUBDOCUMENTs) that aren't anonymous or private browsing.
477 if (StaticPrefs::network_http_windows_sso_enabled() &&
478 mURI->SchemeIs("https") && !(mLoadFlags & LOAD_ANONYMOUS) &&
479 !mPrivateBrowsing) {
480 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
481 if ((type == ExtContentPolicy::TYPE_DOCUMENT ||
482 type == ExtContentPolicy::TYPE_SUBDOCUMENT) &&
483 prefEnabledForCurrentContainer()) {
484 AddWindowsSSO(this);
485 }
486 }
487#endif
488
489#ifdef XP_MACOSX
490
491 auto isUriMSAuthority = [&]() {
492 nsAutoCString endPoint;
493 nsresult rv = mURI->GetHost(endPoint);
494 if (!NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
495 return false;
496 }
497 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)
;
498
499 return gHttpHandler->IsHostMSAuthority(endPoint);
500 };
501
502 // If macOS SSO is enabled, we potentially add auth
503 // information to secure top level loads (DOCUMENTs) and iframes
504 // (SUBDOCUMENTs) that aren't anonymous or private browsing.
505 if (StaticPrefs::network_http_microsoft_entra_sso_enabled() &&
506 mURI->SchemeIs("https") && !(mLoadFlags & LOAD_ANONYMOUS) &&
507 !mPrivateBrowsing) {
508 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
509 nsAutoCString query;
510 nsresult rv = mURI->GetQuery(query);
511 if ((type == ExtContentPolicy::TYPE_DOCUMENT ||
512 type == ExtContentPolicy::TYPE_SUBDOCUMENT) &&
513 NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !query.IsEmpty() &&
514 prefEnabledForCurrentContainer() && isUriMSAuthority()) {
515 nsMainThreadPtrHandle<nsHttpChannel> self(
516 new nsMainThreadPtrHolder<nsHttpChannel>(
517 "nsHttpChannel::PrepareToConnect::self", this));
518 auto resultCallback = [self(self)]() {
519 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 519; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
520 nsresult rv = self->ContinuePrepareToConnect();
521 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
522 self->CloseCacheEntry(false);
523 Unused << self->AsyncAbort(rv);
524 }
525 };
526
527 rv = AddMicrosoftEntraSSO(this, std::move(resultCallback));
528
529 // Returns NS_OK if performRequests is called in MicrosoftEntraSSOUtils
530 // This temporarily stops the channel setup for the delegate.
531 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
532 return rv;
533 }
534 }
535 }
536
537#endif
538
539 return ContinuePrepareToConnect();
540}
541
542nsresult nsHttpChannel::ContinuePrepareToConnect() {
543 // notify "http-on-modify-request" observers
544 CallOnModifyRequestObservers();
545
546 return CallOrWaitForResume(
547 [](auto* self) { return self->OnBeforeConnect(); });
548}
549
550void nsHttpChannel::HandleContinueCancellingByURLClassifier(
551 nsresult aErrorCode) {
552 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 553); AnnotateMozCrashReason("MOZ_ASSERT" "(" "UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { *((volatile int*)__null) = 553; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
553 UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 553); AnnotateMozCrashReason("MOZ_ASSERT" "(" "UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { *((volatile int*)__null) = 553; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
554 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 554; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
555
556 if (mSuspendCount) {
557 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
558 ("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)
559 "[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)
560 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
561 mCallOnResume = [aErrorCode](nsHttpChannel* self) {
562 self->HandleContinueCancellingByURLClassifier(aErrorCode);
563 return NS_OK;
564 };
565 return;
566 }
567
568 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)
569 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
570 ContinueCancellingByURLClassifier(aErrorCode);
571}
572
573void nsHttpChannel::SetPriorityHeader() {
574 nsAutoCString userSetPriority;
575 Unused << GetRequestHeader("Priority"_ns, userSetPriority);
576 if (!userSetPriority.IsEmpty()) {
577 // If the Priority header is set by the user, do not override it.
578 return;
579 }
580
581 uint8_t urgency =
582 nsHttpHandler::UrgencyFromCoSFlags(mClassOfService.Flags(), mPriority);
583 bool incremental = mClassOfService.Incremental();
584
585 nsPrintfCString value(
586 "%s", urgency != 3 ? nsPrintfCString("u=%d", urgency).get() : "");
587
588 if (incremental) {
589 if (!value.IsEmpty()) {
590 value.Append(", ");
591 }
592 value.Append("i");
593 }
594
595 if (!value.IsEmpty()) {
596 SetRequestHeader("Priority"_ns, value, false);
597 }
598}
599
600nsresult nsHttpChannel::OnBeforeConnect() {
601 nsresult rv = NS_OK;
602
603 // Check if request was cancelled during suspend AFTER on-modify-request
604 if (mCanceled) {
605 return mStatus;
606 }
607
608 // Check to see if we should redirect this channel elsewhere by
609 // nsIHttpChannel.redirectTo API request
610 if (mAPIRedirectToURI) {
611 return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
612 }
613
614 // Note that we are only setting the "Upgrade-Insecure-Requests" request
615 // header for *all* navigational requests instead of all requests as
616 // defined in the spec, see:
617 // https://www.w3.org/TR/upgrade-insecure-requests/#preference
618 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
619
620 if (type == ExtContentPolicy::TYPE_DOCUMENT ||
621 type == ExtContentPolicy::TYPE_SUBDOCUMENT) {
622 rv = SetRequestHeader("Upgrade-Insecure-Requests"_ns, "1"_ns, false);
623 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 623); return rv; } } while (false)
;
624 }
625
626 if (LoadAuthRedirectedChannel()) {
627 // This channel is a result of a redirect due to auth retry
628 // We have already checked for HSTS upgarde in the redirecting channel.
629 // We can safely skip those checks
630 return ContinueOnBeforeConnect(false, rv);
631 }
632
633 SecFetch::AddSecFetchHeader(this);
634
635 // Check to see if we should redirect this channel to the unstripped URI. To
636 // revert the query stripping if the loading channel is in the content
637 // blocking allow list.
638 if (ContentBlockingAllowList::Check(this)) {
639 nsCOMPtr<nsIURI> unstrippedURI;
640 mLoadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
641
642 if (unstrippedURI) {
643 return AsyncCall(&nsHttpChannel::HandleAsyncRedirectToUnstrippedURI);
644 }
645 }
646
647 nsCOMPtr<nsIPrincipal> resultPrincipal;
648 if (!mURI->SchemeIs("https")) {
649 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
650 this, getter_AddRefs(resultPrincipal));
651 }
652
653 // Check if we already know about the HSTS status of the host
654 nsISiteSecurityService* sss = gHttpHandler->GetSSService();
655 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 655); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
656 bool isSecureURI;
657 OriginAttributes originAttributes;
658 if (!StoragePrincipalHelper::GetOriginAttributesForHSTS(this,
659 originAttributes)) {
660 return NS_ERROR_FAILURE;
661 }
662 rv = sss->IsSecureURI(mURI, originAttributes, &isSecureURI);
663 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 663); return rv; } } while (false)
;
664 // Save that on the loadInfo so it can later be consumed by
665 // SecurityInfo.sys.mjs
666 mLoadInfo->SetHstsStatus(isSecureURI);
667
668 RefPtr<mozilla::dom::BrowsingContext> bc;
669 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
670 // If bypassing the cache and we're forced offline
671 // we can just return the error here.
672 if (bc && bc->Top()->GetForceOffline() &&
673 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
674 return NS_ERROR_OFFLINE;
675 }
676
677 // At this point it is no longer possible to call
678 // HttpBaseChannel::UpgradeToSecure.
679 StoreUpgradableToSecure(false);
680 bool shouldUpgrade = LoadUpgradeToSecure();
681 if (mURI->SchemeIs("http")) {
682 OriginAttributes originAttributes;
683 if (!StoragePrincipalHelper::GetOriginAttributesForHSTS(this,
684 originAttributes)) {
685 return NS_ERROR_FAILURE;
686 }
687
688 if (!shouldUpgrade) {
689 // Make sure http channel is released on main thread.
690 // See bug 1539148 for details.
691 nsMainThreadPtrHandle<nsHttpChannel> self(
692 new nsMainThreadPtrHolder<nsHttpChannel>(
693 "nsHttpChannel::OnBeforeConnect::self", this));
694 auto resultCallback = [self(self)](bool aResult, nsresult aStatus) {
695 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 695; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
696
697 nsresult rv = self->MaybeUseHTTPSRRForUpgrade(aResult, aStatus);
698 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
699 self->CloseCacheEntry(false);
700 Unused << self->AsyncAbort(rv);
701 }
702 };
703
704 bool willCallback = false;
705 rv = NS_ShouldSecureUpgrade(
706 mURI, mLoadInfo, resultPrincipal, LoadAllowSTS(), originAttributes,
707 shouldUpgrade, std::move(resultCallback), willCallback);
708 // If the request gets upgraded because of the HTTPS-Only mode, but no
709 // event listener has been registered so far, we want to do that here.
710 uint32_t httpOnlyStatus = mLoadInfo->GetHttpsOnlyStatus();
711 if (httpOnlyStatus &
712 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED) {
713 RefPtr<nsHTTPSOnlyStreamListener> httpsOnlyListener =
714 new nsHTTPSOnlyStreamListener(mListener, mLoadInfo);
715 mListener = httpsOnlyListener;
716
717 httpOnlyStatus ^=
718 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED;
719 httpOnlyStatus |= nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED;
720 mLoadInfo->SetHttpsOnlyStatus(httpOnlyStatus);
721 }
722 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
723 ("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)
724 "[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)
725 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)
;
726
727 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || MOZ_UNLIKELY(willCallback)(__builtin_expect(!!(willCallback), 0))) {
728 return rv;
729 }
730 }
731 }
732
733 return MaybeUseHTTPSRRForUpgrade(shouldUpgrade, NS_OK);
734}
735
736// Returns true if the network connectivity checker indicated
737// that HTTPS records can be resolved on this network - false otherwise.
738// When TRR is enabled, we always return true, as resolving HTTPS
739// records don't depend on the network.
740static bool canUseHTTPSRRonNetwork(bool& aTRREnabled) {
741 // Respect the pref.
742 if (StaticPrefs::network_dns_force_use_https_rr()) {
743 aTRREnabled = true;
744 return true;
745 }
746
747 aTRREnabled = false;
748
749 if (nsCOMPtr<nsIDNSService> dns = mozilla::components::DNS::Service()) {
750 nsIDNSService::ResolverMode mode;
751 // If the browser is currently using TRR/DoH, then it can
752 // definitely resolve HTTPS records.
753 if (NS_SUCCEEDED(dns->GetCurrentTrrMode(&mode))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dns->GetCurrentTrrMode
(&mode))), 1)))
) {
754 if (mode == nsIDNSService::MODE_TRRFIRST) {
755 RefPtr<TRRService> trr = TRRService::Get();
756 if (trr && trr->IsConfirmed()) {
757 aTRREnabled = true;
758 }
759 } else if (mode == nsIDNSService::MODE_TRRONLY) {
760 aTRREnabled = true;
761 }
762 if (aTRREnabled) {
763 return true;
764 }
765 }
766 }
767
768 if (RefPtr<NetworkConnectivityService> ncs =
769 NetworkConnectivityService::GetSingleton()) {
770 nsINetworkConnectivityService::ConnectivityState state;
771 if (NS_SUCCEEDED(ncs->GetDNS_HTTPS(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetDNS_HTTPS
(&state))), 1)))
&&
772 state == nsINetworkConnectivityService::NOT_AVAILABLE) {
773 return false;
774 }
775 }
776 return true;
777}
778
779nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade,
780 nsresult aStatus) {
781 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
782 return aStatus;
783 }
784
785 RefPtr<mozilla::dom::BrowsingContext> bc;
786 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
787 bool forceOffline = bc && bc->Top()->GetForceOffline();
788
789 if (mURI->SchemeIs("https") || aShouldUpgrade || !LoadUseHTTPSSVC() ||
790 forceOffline) {
791 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
792 }
793
794 auto shouldSkipUpgradeWithHTTPSRR = [&]() -> bool {
795 if (mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) {
796 return true;
797 }
798
799 // Skip using HTTPS RR to upgrade when this is not a top-level load and the
800 // loading principal is http.
801 if ((mLoadInfo->GetExternalContentPolicyType() !=
802 ExtContentPolicy::TYPE_DOCUMENT) &&
803 (mLoadInfo->GetLoadingPrincipal() &&
804 mLoadInfo->GetLoadingPrincipal()->SchemeIs("http"))) {
805 return true;
806 }
807
808 // If the network connectivity checker indicates the network is
809 // blocking HTTPS requests, then we should skip them so we don't
810 // needlessly wait for a timeout.
811 bool trrEnabled = false;
812 if (!canUseHTTPSRRonNetwork(trrEnabled)) {
813 return true;
814 }
815
816 // Don't block the channel when TRR is not used.
817 if (!trrEnabled) {
818 return true;
819 }
820
821 auto dnsStrategy = GetProxyDNSStrategy();
822 if (dnsStrategy != ProxyDNSStrategy::ORIGIN) {
823 return true;
824 }
825
826 nsAutoCString uriHost;
827 mURI->GetAsciiHost(uriHost);
828
829 return gHttpHandler->IsHostExcludedForHTTPSRR(uriHost);
830 };
831
832 if (shouldSkipUpgradeWithHTTPSRR()) {
833 StoreUseHTTPSSVC(false);
834 // If the website does not want to use HTTPS RR, we should set
835 // NS_HTTP_DISALLOW_HTTPS_RR. This is for avoiding HTTPS RR being used by
836 // the transaction.
837 DisallowHTTPSRR(mCaps);
838 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
839 }
840
841 if (mHTTPSSVCRecord.isSome()) {
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
, "nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] mHTTPSSVCRecord is some"
, this); } } while (0)
843 "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)
844 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
845 StoreWaitHTTPSSVCRecord(false);
846 bool hasHTTPSRR = (mHTTPSSVCRecord.ref() != nullptr);
847 return ContinueOnBeforeConnect(hasHTTPSRR, aStatus, hasHTTPSRR);
848 }
849
850 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)
851 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
852
853 OriginAttributes originAttributes;
854 StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(this, originAttributes);
855
856 RefPtr<nsDNSPrefetch> resolver =
857 new nsDNSPrefetch(mURI, originAttributes, nsIRequest::GetTRRMode());
858 nsWeakPtr weakPtrThis(
859 do_GetWeakReference(static_cast<nsIHttpChannel*>(this)));
860 nsresult rv = resolver->FetchHTTPSSVC(
861 mCaps & NS_HTTP_REFRESH_DNS(1 << 3), !LoadUseHTTPSSVC(),
862 [weakPtrThis](nsIDNSHTTPSSVCRecord* aRecord) {
863 nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(weakPtrThis);
864 RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(channel);
865 if (httpChannelImpl) {
866 httpChannelImpl->OnHTTPSRRAvailable(aRecord);
867 }
868 });
869 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
870 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)
871 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)
;
872 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
873 }
874
875 StoreWaitHTTPSSVCRecord(true);
876 return NS_OK;
877}
878
879nsresult nsHttpChannel::ContinueOnBeforeConnect(bool aShouldUpgrade,
880 nsresult aStatus,
881 bool aUpgradeWithHTTPSRR) {
882 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
883 ("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)
884 "[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)
885 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)
;
886
887 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 887); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadWaitHTTPSSVCRecord()"
")"); do { *((volatile int*)__null) = 887; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
888
889 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
890 return aStatus;
891 }
892
893 if (aShouldUpgrade && !mURI->SchemeIs("https")) {
894 // only set HTTPS_RR to be responsbile for the upgrade in the loadinfo
895 // if it actually was responsible, otherwise the correct flag is
896 // already present in the loadinfo.
897 if (aUpgradeWithHTTPSRR) {
898 mLoadInfo->SetHttpsUpgradeTelemetry(nsILoadInfo::HTTPS_RR);
899 }
900 return AsyncCall(&nsHttpChannel::HandleAsyncRedirectChannelToHttps);
901 }
902
903 // ensure that we are using a valid hostname
904 if (!net_IsValidDNSHost(nsDependentCString(mConnectionInfo->Origin()))) {
905 return NS_ERROR_UNKNOWN_HOST;
906 }
907
908 if (mUpgradeProtocolCallback) {
909 // Websockets can run over HTTP/2, but other upgrades can't.
910 if (mUpgradeProtocol.EqualsLiteral("websocket") &&
911 StaticPrefs::network_http_http2_websockets()) {
912 // Need to tell the conn manager that we're ok with http/2 even with
913 // the allow keepalive bit not set. That bit needs to stay off,
914 // though, in case we end up having to fallback to http/1.1 (where
915 // we absolutely do want to disable keepalive).
916 mCaps |= NS_HTTP_ALLOW_SPDY_WITHOUT_KEEPALIVE(1 << 15);
917 } else {
918 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
919 }
920 // Upgrades cannot use HTTP/3.
921 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
922 // Because NS_HTTP_STICKY_CONNECTION breaks HTTPS RR fallabck mecnahism, we
923 // can not use HTTPS RR for upgrade requests.
924 DisallowHTTPSRR(mCaps);
925 }
926
927 if (LoadIsTRRServiceChannel()) {
928 mCaps |= NS_HTTP_LARGE_KEEPALIVE(1 << 1);
929 DisallowHTTPSRR(mCaps);
930 }
931
932 if (mTransactionSticky) {
933 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadAuthRedirectedChannel()"
")"); do { *((volatile int*)__null) = 933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
934 // this means this is a redirected channel channel due to auth retry and a
935 // connection based auth scheme was used
936 // we have a reference to the old-transaction with sticky connection which
937 // we need to use
938 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
939 }
940
941 mCaps |= NS_HTTP_TRR_FLAGS_FROM_MODE(nsIRequest::GetTRRMode())((static_cast<uint32_t>(nsIRequest::GetTRRMode()) &
3) << 19)
;
942
943 // Finalize ConnectionInfo flags before SpeculativeConnect
944 mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0);
945 mConnectionInfo->SetPrivate(mPrivateBrowsing);
946 mConnectionInfo->SetNoSpdy(mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7));
947 mConnectionInfo->SetBeConservative((mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) ||
948 LoadBeConservative());
949 mConnectionInfo->SetTlsFlags(mTlsFlags);
950 mConnectionInfo->SetIsTrrServiceChannel(LoadIsTRRServiceChannel());
951 mConnectionInfo->SetTRRMode(nsIRequest::GetTRRMode());
952 mConnectionInfo->SetIPv4Disabled(mCaps & NS_HTTP_DISABLE_IPV4(1 << 17));
953 mConnectionInfo->SetIPv6Disabled(mCaps & NS_HTTP_DISABLE_IPV6(1 << 18));
954 mConnectionInfo->SetAnonymousAllowClientCert(
955 (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) != 0);
956
957 if (mWebTransportSessionEventListener) {
958 nsTArray<RefPtr<nsIWebTransportHash>> aServerCertHashes;
959 nsresult rv;
960 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
961 do_QueryInterface(mWebTransportSessionEventListener, &rv);
962 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 962); return rv; } } while (false)
;
963
964 wtconSettings->GetServerCertificateHashes(aServerCertHashes);
965 gHttpHandler->ConnMgr()->StoreServerCertHashes(
966 mConnectionInfo, gHttpHandler->IsHttp2Excluded(mConnectionInfo),
967 !Http3Allowed(), std::move(aServerCertHashes));
968 }
969
970 if (ShouldIntercept()) {
971 return RedirectToInterceptedChannel();
972 }
973
974 // notify "http-on-before-connect" observers
975 gHttpHandler->OnBeforeConnect(this);
976
977 return CallOrWaitForResume([](auto* self) { return self->Connect(); });
978}
979
980class MOZ_STACK_CLASS AddResponseHeadersToResponseHead final
981 : public nsIHttpHeaderVisitor {
982 public:
983 explicit AddResponseHeadersToResponseHead(nsHttpResponseHead* aResponseHead)
984 : mResponseHead(aResponseHead) {}
985
986 NS_IMETHODvirtual nsresult VisitHeader(const nsACString& aHeader,
987 const nsACString& aValue) override {
988 nsAutoCString headerLine = aHeader + ": "_ns + aValue;
989 DebugOnly<nsresult> rv = mResponseHead->ParseHeaderLine(headerLine);
990 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 990; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
991
992 return NS_OK;
993 }
994
995 NS_IMETHODvirtual nsresult QueryInterface(REFNSIIDconst nsIID& aIID, void** aInstancePtr) override;
996
997 // Stub AddRef/Release since this is a stack class.
998 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType AddRef(void) override {
999 return ++mRefCnt;
1000 }
1001
1002 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType Release(void) override {
1003 return --mRefCnt;
1004 }
1005
1006 virtual ~AddResponseHeadersToResponseHead() {
1007 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1007); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mRefCnt == 0"
")"); do { *((volatile int*)__null) = 1007; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1008 }
1009
1010 private:
1011 nsHttpResponseHead* mResponseHead;
1012
1013 nsrefcnt mRefCnt = 0;
1014};
1015
1016NS_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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1016); 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((sizeof(table) / sizeof(table
[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
1017
1018nsresult nsHttpChannel::HandleOverrideResponse() {
1019 // Start building a response with the data from mOverrideResponse.
1020 mResponseHead = MakeUnique<nsHttpResponseHead>();
1021
1022 // Apply override response status code and status text.
1023 uint32_t statusCode;
1024 nsresult rv = mOverrideResponse->GetResponseStatus(&statusCode);
1025 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1025); return rv; } } while (false)
;
1026
1027 nsAutoCString statusText;
1028 rv = mOverrideResponse->GetResponseStatusText(statusText);
1029 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1029); return rv; } } while (false)
;
1030
1031 // Hardcoding protocol HTTP/1.1
1032 nsPrintfCString line("HTTP/1.1 %u %s", statusCode, statusText.get());
1033 rv = mResponseHead->ParseStatusLine(line);
1034 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1034); return rv; } } while (false)
;
1035
1036 // Apply override response headers.
1037 AddResponseHeadersToResponseHead visitor(mResponseHead.get());
1038 rv = mOverrideResponse->VisitResponseHeaders(&visitor);
1039 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1039); return rv; } } while (false)
;
1040
1041 if (WillRedirect(*mResponseHead)) {
1042 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
1043 // to avoid event dispatching latency.
1044 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)
;
1045 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
1046 }
1047
1048 // Handle Set-Cookie headers as if the response was from networking.
1049 if (nsAutoCString cookie;
1050 NS_SUCCEEDED(mResponseHead->GetHeader(nsHttp::Set_Cookie, cookie))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Set_Cookie, cookie))), 1)))
) {
1051 SetCookie(cookie);
1052 nsCOMPtr<nsIParentChannel> parentChannel;
1053 NS_QueryNotificationCallbacks(this, parentChannel);
1054 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
1055 httpParent->SetCookie(std::move(cookie));
1056 }
1057 }
1058
1059 rv = ProcessSecurityHeaders();
1060 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1061 NS_WARNING("ProcessSecurityHeaders failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSecurityHeaders failed, continuing load."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1061)
;
1062 }
1063
1064 if ((statusCode < 500) && (statusCode != 421)) {
1065 ProcessAltService();
1066 }
1067
1068 nsAutoCString body;
1069 rv = mOverrideResponse->GetResponseBody(body);
1070 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1070); return rv; } } while (false)
;
1071
1072 nsCOMPtr<nsIInputStream> stringStream;
1073 rv = NS_NewCStringInputStream(getter_AddRefs(stringStream), body);
1074 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1074); return rv; } } while (false)
;
1075 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), stringStream, 0, 0,
1076 true);
1077 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1078 stringStream->Close();
1079 return rv;
1080 }
1081
1082 rv = mCachePump->AsyncRead(this);
1083 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1084
1085 return NS_OK;
1086}
1087
1088nsresult nsHttpChannel::Connect() {
1089 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)
;
1090
1091 // If mOverrideResponse is set, bypass the rest of the connection and reply
1092 // immediately with a response built using the data from mOverrideResponse.
1093 if (mOverrideResponse) {
1094 return HandleOverrideResponse();
1095 }
1096
1097 // Don't allow resuming when cache must be used
1098 if (LoadResuming() && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
1099 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)
;
1100 return NS_ERROR_DOCUMENT_NOT_CACHED;
1101 }
1102
1103 // Step 8.18 of HTTP-network-or-cache fetch
1104 // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
1105 nsAutoCString rangeVal;
1106 if (NS_SUCCEEDED(GetRequestHeader("Range"_ns, rangeVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Range"_ns, rangeVal))), 1)))
) {
1107 SetRequestHeader("Accept-Encoding"_ns, "identity"_ns, true);
1108 }
1109
1110#ifdef MOZ_WIDGET_ANDROID
1111 bool val = false;
1112 if (nsIOService::ShouldAddAdditionalSearchHeaders(mURI, &val)) {
1113 SetRequestHeader("X-Search-Subdivision"_ns, val ? "1"_ns : "0"_ns, false);
1114 }
1115#endif
1116
1117 bool isTrackingResource = IsThirdPartyTrackingResource();
1118 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)
1119 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)
1120 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)
;
1121
1122 if (isTrackingResource) {
1123 AddClassFlags(nsIClassOfService::Tail);
1124 }
1125
1126 if (WaitingForTailUnblock()) {
1127 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1127); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { *((volatile int*)__null) = 1127; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1128 mOnTailUnblock = &nsHttpChannel::ConnectOnTailUnblock;
1129 return NS_OK;
1130 }
1131
1132 return ConnectOnTailUnblock();
1133}
1134
1135nsresult nsHttpChannel::ConnectOnTailUnblock() {
1136 nsresult rv;
1137
1138 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)
;
1139
1140 // Consider opening a TCP connection right away.
1141 SpeculativeConnect();
1142
1143 // open a cache entry for this channel...
1144 rv = OpenCacheEntry(mURI->SchemeIs("https"));
1145
1146 // do not continue if asyncOpenCacheEntry is in progress
1147 if (AwaitingCacheCallbacks()) {
1148 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)
1149 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
1150 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Unexpected state" ")"); do { *((volatile int*)__null)
= 1150; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1151
1152 if (mNetworkTriggered && mWaitingForProxy) {
1153 // Someone has called TriggerNetwork(), meaning we are racing the
1154 // network with the cache.
1155 mWaitingForProxy = false;
1156 return ContinueConnect();
1157 }
1158
1159 return NS_OK;
1160 }
1161
1162 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1163 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)
1164 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)
;
1165 // if this channel is only allowed to pull from the cache, then
1166 // we must fail if we were unable to open a cache entry.
1167 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1168 return NS_ERROR_DOCUMENT_NOT_CACHED;
1169 }
1170 // otherwise, let's just proceed without using the cache.
1171 }
1172
1173 if (mRaceCacheWithNetwork && ((mCacheEntry && !mCachedContentIsValid &&
1174 (mDidReval || LoadCachedContentIsPartial())) ||
1175 mIgnoreCacheEntry)) {
1176 // We won't send the conditional request because the unconditional
1177 // request was already sent (see bug 1377223).
1178 AccumulateCategorical(
1179 Telemetry::LABELS_NETWORK_RACE_CACHE_VALIDATION::NotSent);
1180 }
1181
1182 // When racing, if OnCacheEntryAvailable is called before AsyncOpenURI
1183 // returns, then we may not have started reading from the cache.
1184 // If the content is valid, we should attempt to do so, as technically the
1185 // cache has won the race.
1186 if (mRaceCacheWithNetwork && mCachedContentIsValid) {
1187 Unused << ReadFromCache();
1188 }
1189
1190 return TriggerNetwork();
1191}
1192
1193nsresult nsHttpChannel::ContinueConnect() {
1194 // If we need to start a CORS preflight, do it now!
1195 // Note that it is important to do this before the early returns below.
1196 if (!LoadIsCorsPreflightDone() && LoadRequireCORSPreflight()) {
1197 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1197); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPreflightChannel"
")"); do { *((volatile int*)__null) = 1197; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1198 nsresult rv = nsCORSListenerProxy::StartCORSPreflight(
1199 this, this, mUnsafeHeaders, getter_AddRefs(mPreflightChannel));
1200 return rv;
1201 }
1202
1203 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1205); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"do the rest of ContinueConnect" ")"); do { *((volatile int*
)__null) = 1205; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1204 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1205); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"do the rest of ContinueConnect" ")"); do { *((volatile int*
)__null) = 1205; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1205 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1205); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"do the rest of ContinueConnect" ")"); do { *((volatile int*
)__null) = 1205; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1206
1207 RefPtr<mozilla::dom::BrowsingContext> bc;
1208 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
1209
1210 // we may or may not have a cache entry at this point
1211 if (mCacheEntry) {
1212 // read straight from the cache if possible...
1213 if (mCachedContentIsValid) {
1214 // If we're forced offline, and set to bypass the cache, return offline.
1215 if (bc && bc->Top()->GetForceOffline() &&
1216 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
1217 return NS_ERROR_OFFLINE;
1218 }
1219
1220 nsRunnableMethod<nsHttpChannel>* event = nullptr;
1221 nsresult rv;
1222 if (!LoadCachedContentIsPartial()) {
1223 rv = AsyncCall(&nsHttpChannel::AsyncOnExamineCachedResponse, &event);
1224 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1225 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)
;
1226 }
1227 }
1228 rv = ReadFromCache();
1229 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && event) {
1230 event->Revoke();
1231 }
1232
1233 AccumulateCacheHitTelemetry(kCacheHit, this);
1234 mCacheDisposition = kCacheHit;
1235
1236 return rv;
1237 }
1238 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1239 // the cache contains the requested resource, but it must be
1240 // validated before we can reuse it. since we are not allowed
1241 // to hit the net, there's nothing more to do. the document
1242 // is effectively not in the cache.
1243 LOG((" !mCachedContentIsValid && 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
, " !mCachedContentIsValid && mLoadFlags & LOAD_ONLY_FROM_CACHE"
); } } while (0)
;
1244 return NS_ERROR_DOCUMENT_NOT_CACHED;
1245 }
1246 } else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1247 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)
;
1248 return NS_ERROR_DOCUMENT_NOT_CACHED;
1249 }
1250
1251 if (mLoadFlags & LOAD_NO_NETWORK_IO) {
1252 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)
;
1253 return NS_ERROR_DOCUMENT_NOT_CACHED;
1254 }
1255
1256 // We're about to hit the network. Don't if we're forced offline.
1257 if (bc && bc->Top()->GetForceOffline()) {
1258 return NS_ERROR_OFFLINE;
1259 }
1260
1261 // hit the net...
1262 nsresult rv = DoConnect(mTransactionSticky);
1263 mTransactionSticky = nullptr;
1264 return rv;
1265}
1266
1267nsresult nsHttpChannel::DoConnect(HttpTransactionShell* aTransWithStickyConn) {
1268 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
)
;
1269
1270 if (!mDNSBlockingPromise.IsEmpty()) {
1271 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)
;
1272
1273 // Transaction is passed only from auth retry for which we will definitely
1274 // not block on DNS to alter the origin server name for IP; it has already
1275 // been done.
1276 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTransWithStickyConn"
")"); do { *((volatile int*)__null) = 1276; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1277 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDNSBlockingThenable"
")"); do { *((volatile int*)__null) = 1277; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1278
1279 nsCOMPtr<nsISerialEventTarget> target(do_GetMainThread());
1280 RefPtr<nsHttpChannel> self(this);
1281 mDNSBlockingThenable->Then(
1282 target, __func__,
1283 [self](const nsCOMPtr<nsIDNSRecord>& aRec) {
1284 nsresult rv = self->DoConnectActual(nullptr);
1285 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1286 self->CloseCacheEntry(false);
1287 Unused << self->AsyncAbort(rv);
1288 }
1289 },
1290 [self](nsresult err) {
1291 self->CloseCacheEntry(false);
1292 Unused << self->AsyncAbort(err);
1293 });
1294
1295 // The connection will continue when the promise is resolved in
1296 // OnLookupComplete.
1297 return NS_OK;
1298 }
1299
1300 return DoConnectActual(aTransWithStickyConn);
1301}
1302
1303nsresult nsHttpChannel::DoConnectActual(
1304 HttpTransactionShell* aTransWithStickyConn) {
1305 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)
1306 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)
;
1307
1308 nsresult rv = SetupChannelForTransaction();
1309 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1310 return rv;
1311 }
1312
1313 return DispatchTransaction(aTransWithStickyConn);
1314}
1315
1316nsresult nsHttpChannel::DispatchTransaction(
1317 HttpTransactionShell* aTransWithStickyConn) {
1318 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)
1319 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)
;
1320 nsresult rv = InitTransaction();
1321 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1322 return rv;
1323 }
1324 if (aTransWithStickyConn) {
1325 rv = gHttpHandler->InitiateTransactionWithStickyConn(
1326 mTransaction, mPriority, aTransWithStickyConn);
1327 } else {
1328 rv = gHttpHandler->InitiateTransaction(mTransaction, mPriority);
1329 }
1330
1331 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1332 return rv;
1333 }
1334
1335 rv = mTransaction->AsyncRead(this, getter_AddRefs(mTransactionPump));
1336 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1337 return rv;
1338 }
1339
1340 uint32_t suspendCount = mSuspendCount;
1341 if (LoadAsyncResumePending()) {
1342 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
1343 (" 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)
1344 ", 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)
1345 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)
;
1346 ++suspendCount;
1347 }
1348 while (suspendCount--) {
1349 mTransactionPump->Suspend();
1350 }
1351
1352 return NS_OK;
1353}
1354
1355void nsHttpChannel::SpeculativeConnect() {
1356 // Before we take the latency hit of dealing with the cache, try and
1357 // get the TCP (and SSL) handshakes going so they can overlap.
1358
1359 // don't speculate if we are offline, when doing http upgrade (i.e.
1360 // websockets bootstrap), or if we can't do keep-alive (because then we
1361 // couldn't reuse the speculative connection anyhow).
1362 RefPtr<mozilla::dom::BrowsingContext> bc;
1363 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
1364
1365 if (gIOService->IsOffline() || mUpgradeProtocolCallback ||
1366 !(mCaps & NS_HTTP_ALLOW_KEEPALIVE(1 << 0)) ||
1367 (bc && bc->Top()->GetForceOffline())) {
1368 return;
1369 }
1370
1371 // LOAD_ONLY_FROM_CACHE and LOAD_NO_NETWORK_IO must not hit network.
1372 // LOAD_FROM_CACHE is unlikely to hit network, so skip preconnects for it.
1373 if (mLoadFlags &
1374 (LOAD_ONLY_FROM_CACHE | LOAD_FROM_CACHE | LOAD_NO_NETWORK_IO)) {
1375 return;
1376 }
1377
1378 if (LoadAllowStaleCacheContent()) {
1379 return;
1380 }
1381
1382 nsCOMPtr<nsIInterfaceRequestor> callbacks;
1383 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
1384 getter_AddRefs(callbacks));
1385 if (!callbacks) return;
1386 bool httpsRRAllowed = !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24));
1387 Unused << gHttpHandler->MaybeSpeculativeConnectWithHTTPSRR(
1388 mConnectionInfo, callbacks,
1389 mCaps & (NS_HTTP_DISALLOW_SPDY(1 << 7) | NS_HTTP_TRR_MODE_MASK((1 << 19) | (1 << 20)) |
1390 NS_HTTP_DISABLE_IPV4(1 << 17) | NS_HTTP_DISABLE_IPV6(1 << 18) |
1391 NS_HTTP_DISALLOW_HTTP3(1 << 21) | NS_HTTP_REFRESH_DNS(1 << 3)),
1392 gHttpHandler->EchConfigEnabled() && httpsRRAllowed);
1393}
1394
1395void nsHttpChannel::DoNotifyListenerCleanup() {
1396 // We don't need this info anymore
1397 CleanRedirectCacheChainIfNecessary();
1398}
1399
1400void nsHttpChannel::ReleaseListeners() {
1401 HttpBaseChannel::ReleaseListeners();
1402 mChannelClassifier = nullptr;
1403 mWarningReporter = nullptr;
1404 mEarlyHintObserver = nullptr;
1405 mWebTransportSessionEventListener = nullptr;
1406
1407 for (StreamFilterRequest& request : mStreamFilterRequests) {
1408 request.mPromise->Reject(false, __func__);
1409 }
1410 mStreamFilterRequests.Clear();
1411}
1412
1413void nsHttpChannel::DoAsyncAbort(nsresult aStatus) {
1414 Unused << AsyncAbort(aStatus);
1415}
1416
1417void nsHttpChannel::HandleAsyncRedirect() {
1418 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 1418; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1419
1420 if (mSuspendCount) {
1421 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)
;
1422 mCallOnResume = [](nsHttpChannel* self) {
1423 self->HandleAsyncRedirect();
1424 return NS_OK;
1425 };
1426 return;
1427 }
1428
1429 nsresult rv = NS_OK;
1430
1431 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)
;
1432
1433 // since this event is handled asynchronously, it is possible that this
1434 // channel could have been canceled, in which case there would be no point
1435 // in processing the redirect.
1436 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) {
1437 PushRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1438 rv = AsyncProcessRedirection(mResponseHead->Status());
1439 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1440 PopRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1441 // TODO: if !DoNotRender3xxBody(), render redirect body instead.
1442 // But first we need to cache 3xx bodies (bug 748510)
1443 rv = ContinueHandleAsyncRedirect(rv);
1444 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1444; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1445 }
1446 } else {
1447 rv = ContinueHandleAsyncRedirect(mStatus);
1448 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1448); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1448; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1449 }
1450}
1451
1452nsresult nsHttpChannel::ContinueHandleAsyncRedirect(nsresult rv) {
1453 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1454 // If AsyncProcessRedirection fails, then we have to send out the
1455 // OnStart/OnStop notifications.
1456 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)
1457 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)
;
1458
1459 bool redirectsEnabled = !mLoadInfo->GetDontFollowRedirects();
1460
1461 if (redirectsEnabled) {
1462 // TODO: stop failing original channel if redirect vetoed?
1463 mStatus = rv;
1464
1465 DoNotifyListener();
1466
1467 // Blow away cache entry if we couldn't process the redirect
1468 // for some reason (the cache entry might be corrupt).
1469 if (mCacheEntry) {
1470 mCacheEntry->AsyncDoom(nullptr);
1471 }
1472 } else {
1473 DoNotifyListener();
1474 }
1475 }
1476
1477 CloseCacheEntry(true);
1478
1479 StoreIsPending(false);
1480
1481 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1482
1483 return NS_OK;
1484}
1485
1486void nsHttpChannel::HandleAsyncNotModified() {
1487 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1487); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 1487; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1488
1489 if (mSuspendCount) {
1490 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)
;
1491 mCallOnResume = [](nsHttpChannel* self) {
1492 self->HandleAsyncNotModified();
1493 return NS_OK;
1494 };
1495 return;
1496 }
1497
1498 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)
;
1499
1500 DoNotifyListener();
1501
1502 CloseCacheEntry(false);
1503
1504 StoreIsPending(false);
1505
1506 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1507}
1508
1509nsresult nsHttpChannel::SetupChannelForTransaction() {
1510 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::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)
1511 "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)
1512 "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)
1513 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)
;
1514
1515 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1515); return NS_ERROR_ALREADY_INITIALIZED; } } while (false
)
;
1516
1517 nsresult rv;
1518
1519 mozilla::MutexAutoLock lock(mRCWNLock);
1520
1521 if (StaticPrefs::network_http_priority_header_enabled()) {
1522 SetPriorityHeader();
1523 }
1524
1525 // If we're racing cache with network, conditional or byte range header
1526 // could be added in OnCacheEntryCheck. We cannot send conditional request
1527 // without having the entry, so we need to remove the headers here and
1528 // ignore the cache entry in OnCacheEntryAvailable.
1529 if (mRaceCacheWithNetwork && AwaitingCacheCallbacks()) {
1530 if (mDidReval) {
1531 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)
;
1532 UntieValidationRequest();
1533 mDidReval = false;
1534 mIgnoreCacheEntry = true;
1535 }
1536
1537 if (LoadCachedContentIsPartial()) {
1538 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)
;
1539 UntieByteRangeRequest();
1540 StoreCachedContentIsPartial(false);
1541 mIgnoreCacheEntry = true;
1542 }
1543
1544 if (mIgnoreCacheEntry) {
1545 mAvailableCachedAltDataType.Truncate();
1546 StoreDeliveringAltData(false);
1547 mAltDataLength = -1;
1548 mCacheInputStream.CloseAndRelease();
1549 }
1550 }
1551
1552 StoreUsedNetwork(1);
1553
1554 if (!LoadAllowSpdy()) {
1555 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
1556 }
1557 if (!LoadAllowHttp3()) {
1558 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
1559 }
1560 if (LoadBeConservative()) {
1561 mCaps |= NS_HTTP_BE_CONSERVATIVE(1 << 11);
1562 }
1563
1564 if (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) {
1565 mCaps |= NS_HTTP_LOAD_ANONYMOUS_CONNECT_ALLOW_CLIENT_CERT(1 << 23);
1566 }
1567
1568 if (nsContentUtils::ShouldResistFingerprinting(this,
1569 RFPTarget::HttpUserAgent)) {
1570 mCaps |= NS_HTTP_USE_RFP(1 << 26);
1571 }
1572
1573 // Use the URI path if not proxying (transparent proxying such as proxy
1574 // CONNECT does not count here). Also figure out what HTTP version to use.
1575 nsAutoCString buf, path;
1576 nsCString* requestURI;
1577
1578 // This is the normal e2e H1 path syntax "/index.html"
1579 rv = mURI->GetPathQueryRef(path);
1580 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1581 return rv;
1582 }
1583
1584 // path may contain UTF-8 characters, so ensure that they're escaped.
1585 if (NS_EscapeURL(path.get(), path.Length(), esc_OnlyNonASCII | esc_Spaces,
1586 buf)) {
1587 requestURI = &buf;
1588 } else {
1589 requestURI = &path;
1590 }
1591
1592 // trim off the #ref portion if any...
1593 int32_t ref1 = requestURI->FindChar('#');
1594 if (ref1 != kNotFound) {
1595 requestURI->SetLength(ref1);
1596 }
1597
1598 if (mConnectionInfo->UsingConnect() || !mConnectionInfo->UsingHttpProxy()) {
1599 mRequestHead.SetVersion(gHttpHandler->HttpVersion());
1600 } else {
1601 mRequestHead.SetPath(*requestURI);
1602
1603 // RequestURI should be the absolute uri H1 proxy syntax
1604 // "http://foo/index.html" so we will overwrite the relative version in
1605 // requestURI
1606 rv = mURI->GetUserPass(buf);
1607 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1608 if (!buf.IsEmpty() && ((strncmp(mSpec.get(), "http:", 5) == 0) ||
1609 strncmp(mSpec.get(), "https:", 6) == 0)) {
1610 nsCOMPtr<nsIURI> tempURI = nsIOService::CreateExposableURI(mURI);
1611 rv = tempURI->GetAsciiSpec(path);
1612 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1613 requestURI = &path;
1614 } else {
1615 requestURI = &mSpec;
1616 }
1617
1618 // trim off the #ref portion if any...
1619 int32_t ref2 = requestURI->FindChar('#');
1620 if (ref2 != kNotFound) {
1621 requestURI->SetLength(ref2);
1622 }
1623
1624 mRequestHead.SetVersion(gHttpHandler->ProxyHttpVersion());
1625 }
1626
1627 mRequestHead.SetRequestURI(*requestURI);
1628
1629 // set the request time for cache expiration calculations
1630 mRequestTime = NowInSeconds()PRTimeToSeconds(PR_Now());
1631 StoreRequestTimeInitialized(true);
1632
1633 // if doing a reload, force end-to-end
1634 if (mLoadFlags & LOAD_BYPASS_CACHE) {
1635 // We need to send 'Pragma:no-cache' to inhibit proxy caching even if
1636 // no proxy is configured since we might be talking with a transparent
1637 // proxy, i.e. one that operates at the network level. See bug #14772.
1638 // But we should not touch Pragma if Cache-Control is already set
1639 // (https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A3)
1640 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1641 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
1642 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1642; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1643 }
1644 // If we're configured to speak HTTP/1.1 then also send 'Cache-control:
1645 // no-cache'. But likewise don't touch Cache-Control if it's already set.
1646 if (mRequestHead.Version() >= HttpVersion::v1_1 &&
1647 !mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1648 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "no-cache", true);
1649 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1649); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1649; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1650 }
1651 } else if (mLoadFlags & VALIDATE_ALWAYS) {
1652 // We need to send 'Cache-Control: max-age=0' to force each cache along
1653 // the path to the origin server to revalidate its own entry, if any,
1654 // with the next cache or server. See bug #84847.
1655 //
1656 // If we're configured to speak HTTP/1.0 then just send 'Pragma: no-cache'
1657 //
1658 // But don't send the headers if they're already set:
1659 // https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A2
1660 if (mRequestHead.Version() >= HttpVersion::v1_1) {
1661 if (!mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1662 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "max-age=0",
1663 true);
1664 }
1665 } else {
1666 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1667 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
1668 }
1669 }
1670 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1670; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1671 }
1672
1673 if (LoadResuming()) {
1674 char byteRange[32];
1675 SprintfLiteral(byteRange, "bytes=%" PRIu64"l" "u" "-", mStartPos);
1676 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(byteRange));
1677 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1677); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1677; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1678
1679 if (!mEntityID.IsEmpty()) {
1680 // Also, we want an error if this resource changed in the meantime
1681 // Format of the entity id is: escaped_etag/size/lastmod
1682 nsCString::const_iterator start, end, slash;
1683 mEntityID.BeginReading(start);
1684 mEntityID.EndReading(end);
1685 mEntityID.BeginReading(slash);
1686
1687 if (FindCharInReadable('/', slash, end)) {
1688 nsAutoCString ifMatch;
1689 rv = mRequestHead.SetHeader(
1690 nsHttp::If_Match,
1691 NS_UnescapeURL(Substring(start, slash), 0, ifMatch));
1692 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1692); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1692; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1693
1694 ++slash; // Incrementing, so that searching for '/' won't find
1695 // the same slash again
1696 }
1697
1698 if (FindCharInReadable('/', slash, end)) {
1699 rv = mRequestHead.SetHeader(nsHttp::If_Unmodified_Since,
1700 Substring(++slash, end));
1701 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1701); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1701; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1702 }
1703 }
1704 }
1705
1706 // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
1707 if (mLoadFlags & LOAD_ANONYMOUS) mCaps |= NS_HTTP_LOAD_ANONYMOUS(1 << 4);
1708
1709 if (LoadTimingEnabled()) mCaps |= NS_HTTP_TIMING_ENABLED(1 << 5);
1710
1711 if (mUpgradeProtocolCallback) {
1712 rv = mRequestHead.SetHeader(nsHttp::Upgrade, mUpgradeProtocol, false);
1713 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1713; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1714 rv = mRequestHead.SetHeaderOnce(nsHttp::Connection, nsHttp::Upgrade.get(),
1715 true);
1716 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1716); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1716; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1717 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
1718 mCaps &= ~NS_HTTP_ALLOW_KEEPALIVE(1 << 0);
1719 }
1720
1721 if (mWebTransportSessionEventListener) {
1722 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
1723 }
1724
1725 return NS_OK;
1726}
1727
1728nsresult nsHttpChannel::InitTransaction() {
1729 nsresult rv;
1730 // create wrapper for this channel's notification callbacks
1731 nsCOMPtr<nsIInterfaceRequestor> callbacks;
1732 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
1733 getter_AddRefs(callbacks));
1734
1735 // create the transaction object
1736 if (nsIOService::UseSocketProcess()) {
1737 if (NS_WARN_IF(!gIOService->SocketProcessReady())NS_warn_if_impl(!gIOService->SocketProcessReady(), "!gIOService->SocketProcessReady()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1737)
) {
1738 return NS_ERROR_NOT_AVAILABLE;
1739 }
1740 RefPtr<SocketProcessParent> socketProcess =
1741 SocketProcessParent::GetSingleton();
1742 if (!socketProcess->CanSend()) {
1743 return NS_ERROR_NOT_AVAILABLE;
1744 }
1745
1746 nsCOMPtr<nsIParentChannel> parentChannel;
1747 NS_QueryNotificationCallbacks(this, parentChannel);
1748 RefPtr<DocumentLoadListener> documentChannelParent =
1749 do_QueryObject(parentChannel);
1750 // See HttpTransactionChild::CanSendODAToContentProcessDirectly() and
1751 // nsHttpChannel::CallOnStartRequest() for the reason why we need to know if
1752 // this is a document load. We only send ODA directly to child process for
1753 // non document loads.
1754 RefPtr<HttpTransactionParent> transParent =
1755 new HttpTransactionParent(!!documentChannelParent);
1756 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)
1757 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)
;
1758
1759 // Since OnStopRequest could be sent to child process from socket process
1760 // directly, we need to store these two values in HttpTransactionChild and
1761 // forward to child process until HttpTransactionChild::OnStopRequest is
1762 // called.
1763 transParent->SetRedirectTimestamp(mRedirectStartTimeStamp,
1764 mRedirectEndTimeStamp);
1765
1766 if (socketProcess) {
1767 MOZ_ALWAYS_TRUE(do { if ((__builtin_expect(!!(socketProcess->SendPHttpTransactionConstructor
(transParent)), 1))) { } else { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(false)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1768); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")"); do { *((volatile int*)__null) = 1768; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1768 socketProcess->SendPHttpTransactionConstructor(transParent))do { if ((__builtin_expect(!!(socketProcess->SendPHttpTransactionConstructor
(transParent)), 1))) { } else { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(false)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1768); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")"); do { *((volatile int*)__null) = 1768; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1769 }
1770 mTransaction = transParent;
1771 } else {
1772 mTransaction = new nsHttpTransaction();
1773 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)
1774 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)
;
1775 }
1776
1777 // Save the mapping of channel id and the channel. We need this mapping for
1778 // nsIHttpActivityObserver.
1779 gHttpHandler->AddHttpChannel(mChannelId, ToSupports(this));
1780
1781 nsCOMPtr<nsIHttpPushListener> pushListener;
1782 NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
1783 NS_GET_IID(nsIHttpPushListener)(nsIHttpPushListener::COMTypeInfo<nsIHttpPushListener, void
>::kIID)
,
1784 getter_AddRefs(pushListener));
1785 HttpTransactionShell::OnPushCallback pushCallback = nullptr;
1786 if (pushListener) {
1787 mCaps |= NS_HTTP_ONPUSH_LISTENER(1 << 9);
1788 nsWeakPtr weakPtrThis(
1789 do_GetWeakReference(static_cast<nsIHttpChannel*>(this)));
1790 pushCallback = [weakPtrThis](uint32_t aPushedStreamId,
1791 const nsACString& aUrl,
1792 const nsACString& aRequestString,
1793 HttpTransactionShell* aTransaction) {
1794 if (nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(weakPtrThis)) {
1795 return static_cast<nsHttpChannel*>(channel.get())
1796 ->OnPush(aPushedStreamId, aUrl, aRequestString, aTransaction);
1797 }
1798 return NS_ERROR_NOT_AVAILABLE;
1799 };
1800 }
1801
1802 EnsureBrowserId();
1803 EnsureRequestContext();
1804
1805 HttpTrafficCategory category = CreateTrafficCategory();
1806 std::function<void(TransactionObserverResult&&)> observer;
1807 if (mTransactionObserver) {
1808 observer = [transactionObserver{std::move(mTransactionObserver)}](
1809 TransactionObserverResult&& aResult) {
1810 transactionObserver->Complete(aResult.versionOk(), aResult.authOk(),
1811 aResult.closeReason());
1812 };
1813 }
1814 mTransaction->SetIsForWebTransport(!!mWebTransportSessionEventListener);
1815 rv = mTransaction->Init(
1816 mCaps, mConnectionInfo, &mRequestHead, mUploadStream, mReqContentLength,
1817 LoadUploadStreamHasHeaders(), GetCurrentSerialEventTarget(), callbacks,
1818 this, mBrowserId, category, mRequestContext, mClassOfService,
1819 mInitialRwin, LoadResponseTimeoutEnabled(), mChannelId,
1820 std::move(observer), std::move(pushCallback), mTransWithPushedStream,
1821 mPushedStreamId);
1822 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1823 mTransaction = nullptr;
1824 return rv;
1825 }
1826
1827 return rv;
1828}
1829
1830HttpTrafficCategory nsHttpChannel::CreateTrafficCategory() {
1831 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { *((volatile int*)__null) = 1832; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1832 !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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { *((volatile int*)__null) = 1832; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1833
1834 if (!StaticPrefs::network_traffic_analyzer_enabled()) {
1835 return HttpTrafficCategory::eInvalid;
1836 }
1837
1838 HttpTrafficAnalyzer::ClassOfService cos;
1839 {
1840 if ((mClassOfService.Flags() & nsIClassOfService::Leader) &&
1841 mLoadInfo->GetExternalContentPolicyType() ==
1842 ExtContentPolicy::TYPE_SCRIPT) {
1843 cos = HttpTrafficAnalyzer::ClassOfService::eLeader;
1844 } else if (mLoadFlags & nsIRequest::LOAD_BACKGROUND) {
1845 cos = HttpTrafficAnalyzer::ClassOfService::eBackground;
1846 } else {
1847 cos = HttpTrafficAnalyzer::ClassOfService::eOther;
1848 }
1849 }
1850
1851 bool isThirdParty = AntiTrackingUtils::IsThirdPartyChannel(this);
1852
1853 HttpTrafficAnalyzer::TrackingClassification tc;
1854 {
1855 uint32_t flags = isThirdParty ? mThirdPartyClassificationFlags
1856 : mFirstPartyClassificationFlags;
1857
1858 using CF = nsIClassifiedChannel::ClassificationFlags;
1859 using TC = HttpTrafficAnalyzer::TrackingClassification;
1860
1861 if (flags & CF::CLASSIFIED_TRACKING_CONTENT) {
1862 tc = TC::eContent;
1863 } else if (flags & CF::CLASSIFIED_FINGERPRINTING_CONTENT) {
1864 tc = TC::eFingerprinting;
1865 } else if (flags & CF::CLASSIFIED_ANY_BASIC_TRACKING) {
1866 tc = TC::eBasic;
1867 } else {
1868 tc = TC::eNone;
1869 }
1870 }
1871
1872 bool isSystemPrincipal =
1873 mLoadInfo->GetLoadingPrincipal() &&
1874 mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal();
1875 return HttpTrafficAnalyzer::CreateTrafficCategory(
1876 NS_UsePrivateBrowsing(this), isSystemPrincipal, isThirdParty, cos, tc);
1877}
1878
1879void nsHttpChannel::SetCachedContentType() {
1880 if (!mResponseHead) {
1881 return;
1882 }
1883
1884 nsAutoCString contentTypeStr;
1885 mResponseHead->ContentType(contentTypeStr);
1886
1887 uint8_t contentType = nsICacheEntry::CONTENT_TYPE_OTHER;
1888 if (nsContentUtils::IsJavascriptMIMEType(
1889 NS_ConvertUTF8toUTF16(contentTypeStr))) {
1890 contentType = nsICacheEntry::CONTENT_TYPE_JAVASCRIPT;
1891 } else if (StringBeginsWith(contentTypeStr, "text/css"_ns) ||
1892 (mLoadInfo->GetExternalContentPolicyType() ==
1893 ExtContentPolicy::TYPE_STYLESHEET)) {
1894 contentType = nsICacheEntry::CONTENT_TYPE_STYLESHEET;
1895 } else if (StringBeginsWith(contentTypeStr, "application/wasm"_ns)) {
1896 contentType = nsICacheEntry::CONTENT_TYPE_WASM;
1897 } else if (StringBeginsWith(contentTypeStr, "image/"_ns)) {
1898 contentType = nsICacheEntry::CONTENT_TYPE_IMAGE;
1899 } else if (StringBeginsWith(contentTypeStr, "video/"_ns)) {
1900 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
1901 } else if (StringBeginsWith(contentTypeStr, "audio/"_ns)) {
1902 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
1903 }
1904
1905 mCacheEntry->SetContentType(contentType);
1906}
1907
1908nsresult nsHttpChannel::CallOnStartRequest() {
1909 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)
;
1910
1911 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1913); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { *((volatile int*)__null) = 1913
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1912 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1913); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { *((volatile int*)__null) = 1913
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1913 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1913); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { *((volatile int*)__null) = 1913
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1914
1915 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1917); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { *((volatile int*)__null
) = 1917; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
1916 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1917); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { *((volatile int*)__null
) = 1917; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
1917 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1917); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { *((volatile int*)__null
) = 1917; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1918
1919 mEarlyHintObserver = nullptr;
1920
1921 if (StaticPrefs::network_http_network_error_logging_enabled() &&
1922 mResponseHead && mResponseHead->HasHeader(nsHttp::NEL) &&
1923 LoadUsedNetwork()) {
1924 // If the policy gets cleared, but this response is still in the cache,
1925 // we probably don't want to reinstall the policy when the entry is
1926 // reloaded. That means it's important to only call RegisterPolicy when
1927 // LoadUsedNetwork() is true.
1928 if (nsCOMPtr<nsINetworkErrorLogging> nel =
1929 components::NetworkErrorLogging::Service()) {
1930 nel->RegisterPolicy(this);
1931 }
1932 }
1933
1934 if (LoadOnStartRequestCalled()) {
1935 // This can only happen when a range request loading rest of the data
1936 // after interrupted concurrent cache read asynchronously failed, e.g.
1937 // the response range bytes are not as expected or this channel has
1938 // been externally canceled.
1939 //
1940 // It's legal to bypass CallOnStartRequest for that case since we've
1941 // already called OnStartRequest on our listener and also added all
1942 // content converters before.
1943 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { *((volatile int*)__null) = 1943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1944 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)
;
1945 return mStatus;
1946 }
1947
1948 // Ensure mListener->OnStartRequest will be invoked before exiting
1949 // this function.
1950 auto onStartGuard = MakeScopeExit([&] {
1951 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
1952 (" 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)
1953 "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)
1954 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)
;
1955 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 1955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { *((volatile int*)__null) = 1955; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1956
1957 if (mListener) {
1958 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
1959 StoreOnStartRequestCalled(true);
1960 deleteProtector->OnStartRequest(this);
1961 }
1962 StoreOnStartRequestCalled(true);
1963 });
1964
1965 nsresult rv = ValidateMIMEType();
1966 // Since ODA and OnStopRequest could be sent from socket process directly, we
1967 // need to update the channel status before calling mListener->OnStartRequest.
1968 // This is the only way to let child process discard the already received ODA
1969 // messages.
1970 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1971 mStatus = rv;
1972 return mStatus;
1973 }
1974
1975 // EnsureOpaqueResponseIsAllowed and EnsureOpauqeResponseIsAllowedAfterSniff
1976 // are the checks for Opaque Response Blocking to ensure that we block as many
1977 // cross-origin responses with CORS headers as possible that are not either
1978 // Javascript or media to avoid leaking their contents through side channels.
1979 OpaqueResponse opaqueResponse =
1980 PerformOpaqueResponseSafelistCheckBeforeSniff();
1981 if (opaqueResponse == OpaqueResponse::Block) {
1982 SetChannelBlockedByOpaqueResponse();
1983 CancelWithReason(NS_BINDING_ABORTED,
1984 "OpaqueResponseBlocker::BlockResponse"_ns);
1985 return NS_BINDING_ABORTED;
1986 }
1987
1988 // Allow consumers to override our content type
1989 if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) {
1990 // NOTE: We can have both a txn pump and a cache pump when the cache
1991 // content is partial. In that case, we need to read from the cache,
1992 // because that's the one that has the initial contents. If that fails
1993 // then give the transaction pump a shot.
1994
1995 nsIChannel* thisChannel = static_cast<nsIChannel*>(this);
1996
1997 bool typeSniffersCalled = false;
1998 if (mCachePump) {
1999 typeSniffersCalled =
2000 NS_SUCCEEDED(mCachePump->PeekStream(CallTypeSniffers, thisChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCachePump->PeekStream
(CallTypeSniffers, thisChannel))), 1)))
;
2001 }
2002
2003 if (!typeSniffersCalled && mTransactionPump) {
2004 RefPtr<nsInputStreamPump> pump = do_QueryObject(mTransactionPump);
2005 if (pump) {
2006 pump->PeekStream(CallTypeSniffers, thisChannel);
2007 } else {
2008 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()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsIOService::UseSocketProcess()"
")"); do { *((volatile int*)__null) = 2008; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2009 RefPtr<HttpTransactionParent> trans = do_QueryObject(mTransactionPump);
2010 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "trans" ")")
; do { *((volatile int*)__null) = 2010; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2011 trans->SetSniffedTypeToChannel(CallTypeSniffers, thisChannel);
2012 }
2013 }
2014 }
2015
2016 // Note that the code below should be synced with the code in
2017 // HttpTransactionChild::CanSendODAToContentProcessDirectly(). We MUST make
2018 // sure HttpTransactionChild::CanSendODAToContentProcessDirectly() returns
2019 // false when a stream converter is applied.
2020 bool unknownDecoderStarted = false;
2021 if (mResponseHead && !mResponseHead->HasContentType()) {
2022 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo"
") (" "Should have connection info here" ")"); do { *((volatile
int*)__null) = 2022; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2023 if (!mContentTypeHint.IsEmpty()) {
2024 mResponseHead->SetContentType(mContentTypeHint);
2025 } else if (mResponseHead->Version() == HttpVersion::v0_9 &&
2026 mConnectionInfo->OriginPort() !=
2027 mConnectionInfo->DefaultPort()) {
2028 mResponseHead->SetContentType(nsLiteralCString(TEXT_PLAIN"text/plain"));
2029 } else {
2030 // Uh-oh. We had better find out what type we are!
2031 mListener = new nsUnknownDecoder(mListener);
2032 unknownDecoderStarted = true;
2033 }
2034 }
2035
2036 // If unknownDecoder is not going to be launched, call
2037 // EnsureOpaqueResponseIsAllowedAfterSniff immediately.
2038 if (!unknownDecoderStarted) {
2039 if (opaqueResponse == OpaqueResponse::SniffCompressed) {
2040 mListener = new nsCompressedAudioVideoImageDetector(
2041 mListener, &HttpBaseChannel::CallTypeSniffers);
2042 } else if (opaqueResponse == OpaqueResponse::Sniff) {
2043 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2043); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mORB"
")"); do { *((volatile int*)__null) = 2043; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2044 nsresult rv = mORB->EnsureOpaqueResponseIsAllowedAfterSniff(this);
2045
2046 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2047 return rv;
2048 }
2049 }
2050 }
2051
2052 // If the content is multipart/x-mixed-replace, we'll insert a MIME decoder
2053 // in the pipeline to handle the content and pass it along to our
2054 // original listener. nsUnknownDecoder doesn't support detecting this type,
2055 // so we only need to insert this using the response header's mime type.
2056 //
2057 // We only do this for unwrapped document loads, since we might want to send
2058 // parts to the external protocol handler without leaving the parent process.
2059 bool mustRunStreamFilterInParent = false;
2060 nsCOMPtr<nsIParentChannel> parentChannel;
2061 NS_QueryNotificationCallbacks(this, parentChannel);
2062 RefPtr<DocumentLoadListener> docListener = do_QueryObject(parentChannel);
2063 if (mResponseHead && docListener && docListener->GetChannel() == this) {
2064 nsAutoCString contentType;
2065 mResponseHead->ContentType(contentType);
2066
2067 if (contentType.Equals("multipart/x-mixed-replace"_ns)) {
2068 nsCOMPtr<nsIStreamConverterService> convServ(
2069 mozilla::components::StreamConverter::Service(&rv));
2070 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2071 nsCOMPtr<nsIStreamListener> toListener(mListener);
2072 nsCOMPtr<nsIStreamListener> fromListener;
2073
2074 rv = convServ->AsyncConvertData("multipart/x-mixed-replace", "*/*",
2075 toListener, nullptr,
2076 getter_AddRefs(fromListener));
2077 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2078 mListener = fromListener;
2079 mustRunStreamFilterInParent = true;
2080 }
2081 }
2082 }
2083 }
2084
2085 // If we installed a multipart converter, then we need to add StreamFilter
2086 // object before it, so that extensions see the un-parsed original stream.
2087 // We may want to add an option for extensions to opt-in to proper multipart
2088 // handling.
2089 // If not, then pass the StreamFilter promise on to DocumentLoadListener,
2090 // where it'll be added in the content process.
2091 for (StreamFilterRequest& request : mStreamFilterRequests) {
2092 if (mustRunStreamFilterInParent) {
2093 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
2094 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
2095 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
2096 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2097 request.mPromise->Reject(false, __func__);
2098 } else {
2099 extensions::StreamFilterParent::Attach(this, std::move(parent));
2100 request.mPromise->Resolve(std::move(child), __func__);
2101 }
2102 } else {
2103 if (docListener) {
2104 docListener->AttachStreamFilter()->ChainTo(request.mPromise.forget(),
2105 __func__);
2106 } else {
2107 request.mPromise->Reject(false, __func__);
2108 }
2109 }
2110 request.mPromise = nullptr;
2111 }
2112 mStreamFilterRequests.Clear();
2113 StoreTracingEnabled(false);
2114
2115 if (mResponseHead && !mResponseHead->HasContentCharset()) {
2116 mResponseHead->SetContentCharset(mContentCharsetHint);
2117 }
2118
2119 if (mCacheEntry && LoadCacheEntryIsWriteOnly()) {
2120 SetCachedContentType();
2121 }
2122
2123 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)
2124 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)
;
2125
2126 // About to call OnStartRequest, dismiss the guard object.
2127 onStartGuard.release();
2128
2129 if (mListener) {
2130 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { *
((volatile int*)__null) = 2131; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
2131 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { *
((volatile int*)__null) = 2131; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
2132 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
2133 StoreOnStartRequestCalled(true);
2134 rv = deleteProtector->OnStartRequest(this);
2135 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2136 } else {
2137 NS_WARNING("OnStartRequest skipped because of null listener")NS_DebugBreak(NS_DEBUG_WARNING, "OnStartRequest skipped because of null listener"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2137)
;
2138 StoreOnStartRequestCalled(true);
2139 }
2140
2141 // Install stream converter if required.
2142 // Normally, we expect the listener to disable content conversion during
2143 // OnStartRequest if it wants to handle it itself (which is common case with
2144 // HttpChannelParent, disabling so that it can be done in the content
2145 // process). If we've installed an nsUnknownDecoder, then we won't yet have
2146 // called OnStartRequest on the final listener (that happens after we send
2147 // OnDataAvailable to the nsUnknownDecoder), so it can't yet have disabled
2148 // content conversion.
2149 // In that case, assume that the listener will disable content conversion,
2150 // unless it's specifically told us that it won't.
2151 if (!unknownDecoderStarted || LoadListenerRequiresContentConversion()) {
2152 nsCOMPtr<nsIStreamListener> listener;
2153 rv =
2154 DoApplyContentConversions(mListener, getter_AddRefs(listener), nullptr);
2155 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2156 return rv;
2157 }
2158 if (listener) {
2159 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."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2162); 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 { *((volatile int*)__null) = 2162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2160 "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."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2162); 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 { *((volatile int*)__null) = 2162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2161 "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."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2162); 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 { *((volatile int*)__null) = 2162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2162 "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."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2162); 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 { *((volatile int*)__null) = 2162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2163 mListener = listener;
2164 mCompressListener = listener;
2165
2166 StoreHasAppliedConversion(true);
2167 }
2168 }
2169
2170 // if this channel is for a download, close off access to the cache.
2171 if (mCacheEntry && LoadChannelIsForDownload()) {
2172 mCacheEntry->AsyncDoom(nullptr);
2173
2174 // We must keep the cache entry in case of partial request.
2175 // Concurrent access is the same, we need the entry in
2176 // OnStopRequest.
2177 // We also need the cache entry when racing cache with network to find
2178 // out what is the source of the data.
2179 if (!LoadCachedContentIsPartial() && !LoadConcurrentCacheAccess() &&
2180 !(mRaceCacheWithNetwork &&
2181 mFirstResponseSource == RESPONSE_FROM_CACHE)) {
2182 CloseCacheEntry(false);
2183 }
2184 }
2185
2186 return NS_OK;
2187}
2188
2189NS_IMETHODIMPnsresult nsHttpChannel::GetHttpProxyConnectResponseCode(
2190 int32_t* aResponseCode) {
2191 NS_ENSURE_ARG_POINTER(aResponseCode)do { if ((__builtin_expect(!!(!(aResponseCode)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResponseCode" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2191); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2192
2193 if (mConnectionInfo && mConnectionInfo->UsingConnect()) {
2194 *aResponseCode = mProxyConnectResponseCode;
2195 } else {
2196 *aResponseCode = -1;
2197 }
2198 return NS_OK;
2199}
2200
2201nsresult nsHttpChannel::ProcessFailedProxyConnect(uint32_t httpStatus) {
2202 // Failure to set up a proxy tunnel via CONNECT means one of the following:
2203 // 1) Proxy wants authorization, or forbids.
2204 // 2) DNS at proxy couldn't resolve target URL.
2205 // 3) Proxy connection to target failed or timed out.
2206 // 4) Eve intercepted our CONNECT, and is replying with malicious HTML.
2207 //
2208 // Our current architecture would parse the proxy's response content with
2209 // the permission of the target URL. Given #4, we must avoid rendering the
2210 // body of the reply, and instead give the user a (hopefully helpful)
2211 // boilerplate error page, based on just the HTTP status of the reply.
2212
2213 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?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ *((volatile int*)__null) = 2214; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2214 "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?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ *((volatile int*)__null) = 2214; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2215 nsresult rv = HttpProxyResponseToErrorCode(httpStatus);
2216 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)
2217 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)
;
2218
2219 // Make sure the connection is thrown away as it can be in a bad state
2220 // and the proxy may just hang on the next request.
2221 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { *((volatile int*)__null) = 2221; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2222 mTransaction->DontReuseConnection();
2223
2224 Cancel(rv);
2225 {
2226 nsresult rv = CallOnStartRequest();
2227 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2228 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)
2229 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)
;
2230 }
2231 }
2232 return rv;
2233}
2234
2235static void GetSTSConsoleErrorTag(uint32_t failureResult,
2236 nsAString& consoleErrorTag) {
2237 switch (failureResult) {
2238 case nsISiteSecurityService::ERROR_COULD_NOT_PARSE_HEADER:
2239 consoleErrorTag = u"STSCouldNotParseHeader"_ns;
2240 break;
2241 case nsISiteSecurityService::ERROR_NO_MAX_AGE:
2242 consoleErrorTag = u"STSNoMaxAge"_ns;
2243 break;
2244 case nsISiteSecurityService::ERROR_MULTIPLE_MAX_AGES:
2245 consoleErrorTag = u"STSMultipleMaxAges"_ns;
2246 break;
2247 case nsISiteSecurityService::ERROR_INVALID_MAX_AGE:
2248 consoleErrorTag = u"STSInvalidMaxAge"_ns;
2249 break;
2250 case nsISiteSecurityService::ERROR_MULTIPLE_INCLUDE_SUBDOMAINS:
2251 consoleErrorTag = u"STSMultipleIncludeSubdomains"_ns;
2252 break;
2253 case nsISiteSecurityService::ERROR_INVALID_INCLUDE_SUBDOMAINS:
2254 consoleErrorTag = u"STSInvalidIncludeSubdomains"_ns;
2255 break;
2256 case nsISiteSecurityService::ERROR_COULD_NOT_SAVE_STATE:
2257 consoleErrorTag = u"STSCouldNotSaveState"_ns;
2258 break;
2259 default:
2260 consoleErrorTag = u"STSUnknownError"_ns;
2261 break;
2262 }
2263}
2264
2265/**
2266 * Process an HTTP Strict Transport Security (HSTS) header.
2267 */
2268nsresult nsHttpChannel::ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo) {
2269 nsHttpAtom atom(nsHttp::ResolveAtom("Strict-Transport-Security"_ns));
2270
2271 nsAutoCString securityHeader;
2272 nsresult rv = mResponseHead->GetHeader(atom, securityHeader);
2273 if (rv == NS_ERROR_NOT_AVAILABLE) {
2274 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)
;
2275 return NS_OK;
2276 }
2277 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2277)
) {
2278 return rv;
2279 }
2280
2281 if (!aSecInfo) {
2282 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)
;
2283 return NS_ERROR_INVALID_ARG;
2284 }
2285 nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
2286 rv = aSecInfo->GetOverridableErrorCategory(&overridableErrorCategory);
2287 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2287)
) {
2288 return rv;
2289 }
2290 if (overridableErrorCategory !=
2291 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
2292 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
2293 ("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)
2294 "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)
;
2295 return NS_ERROR_FAILURE;
2296 }
2297
2298 nsISiteSecurityService* sss = gHttpHandler->GetSSService();
2299 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2299); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2300
2301 OriginAttributes originAttributes;
2302 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2303)
2303 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2303)
) {
2304 return NS_ERROR_FAILURE;
2305 }
2306
2307 uint32_t failureResult;
2308 rv = sss->ProcessHeader(mURI, securityHeader, originAttributes, nullptr,
2309 nullptr, &failureResult);
2310 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2311 nsAutoString consoleErrorCategory(u"Invalid HSTS Headers"_ns);
2312 nsAutoString consoleErrorTag;
2313 GetSTSConsoleErrorTag(failureResult, consoleErrorTag);
2314 Unused << AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2315 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)
2316 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)
;
2317 }
2318 return NS_OK;
2319}
2320
2321/**
2322 * Decide whether or not to remember Strict-Transport-Security, and whether
2323 * or not to enforce channel integrity.
2324 *
2325 * @return NS_ERROR_FAILURE if there's security information missing even though
2326 * it's an HTTPS connection.
2327 */
2328nsresult nsHttpChannel::ProcessSecurityHeaders() {
2329 // If this channel is not loading securely, STS or PKP doesn't do anything.
2330 // In the case of HSTS, the upgrade to HTTPS takes place earlier in the
2331 // channel load process.
2332 if (!mURI->SchemeIs("https")) {
2333 return NS_OK;
2334 }
2335
2336 if (IsBrowsingContextDiscarded()) {
2337 return NS_OK;
2338 }
2339
2340 nsAutoCString asciiHost;
2341 nsresult rv = mURI->GetAsciiHost(asciiHost);
2342 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2342); return NS_OK; } } while (false)
;
2343
2344 // If the channel is not a hostname, but rather an IP, do not process STS
2345 // or PKP headers
2346 if (HostIsIPLiteral(asciiHost)) {
2347 return NS_OK;
2348 }
2349
2350 // mSecurityInfo may not always be present, and if it's not then it is okay
2351 // to just disregard any security headers since we know nothing about the
2352 // security of the connection.
2353 NS_ENSURE_TRUE(mSecurityInfo, NS_OK)do { if ((__builtin_expect(!!(!(mSecurityInfo)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mSecurityInfo" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2353); return NS_OK; } } while (false)
;
2354
2355 // Only process HSTS headers for first-party loads. This prevents a
2356 // proliferation of useless HSTS state for partitioned third parties.
2357 if (!mLoadInfo->GetIsThirdPartyContextToTopWindow()) {
2358 rv = ProcessHSTSHeader(mSecurityInfo);
2359 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2359); return rv; } } while (false)
;
2360 }
2361
2362 return NS_OK;
2363}
2364
2365bool nsHttpChannel::IsHTTPS() { return mURI->SchemeIs("https"); }
2366
2367void nsHttpChannel::ProcessSSLInformation() {
2368 // If this is HTTPS, record any use of RSA so that Key Exchange Algorithm
2369 // can be whitelisted for TLS False Start in future sessions. We could
2370 // do the same for DH but its rarity doesn't justify the lookup.
2371
2372 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) || !mSecurityInfo || !IsHTTPS() ||
2373 mPrivateBrowsing) {
2374 return;
2375 }
2376
2377 if (!mSecurityInfo) {
2378 return;
2379 }
2380
2381 uint32_t state;
2382 if (NS_SUCCEEDED(mSecurityInfo->GetSecurityState(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mSecurityInfo->
GetSecurityState(&state))), 1)))
&&
2383 (state & nsIWebProgressListener::STATE_IS_BROKEN)) {
2384 // Send weak crypto warnings to the web console
2385 if (state & nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
2386 nsString consoleErrorTag = u"WeakCipherSuiteWarning"_ns;
2387 nsString consoleErrorCategory = u"SSL"_ns;
2388 Unused << AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2389 }
2390 }
2391
2392 uint16_t tlsVersion;
2393 nsresult rv = mSecurityInfo->GetProtocolVersion(&tlsVersion);
2394 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
2395 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_2 &&
2396 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_3) {
2397 nsString consoleErrorTag = u"DeprecatedTLSVersion2"_ns;
2398 nsString consoleErrorCategory = u"TLS"_ns;
2399 Unused << AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2400 }
2401}
2402
2403void nsHttpChannel::ProcessAltService() {
2404 // e.g. Alt-Svc: h2=":443"; ma=60
2405 // e.g. Alt-Svc: h2="otherhost:443"
2406 // Alt-Svc = 1#( alternative *( OWS ";" OWS parameter ) )
2407 // alternative = protocol-id "=" alt-authority
2408 // protocol-id = token ; percent-encoded ALPN protocol identifier
2409 // alt-authority = quoted-string ; containing [ uri-host ] ":" port
2410
2411 if (!LoadAllowAltSvc()) { // per channel opt out
2412 return;
2413 }
2414
2415 if (mWebTransportSessionEventListener) {
2416 return;
2417 }
2418
2419 if (!gHttpHandler->AllowAltSvc() || (mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7))) {
2420 return;
2421 }
2422
2423 if (IsBrowsingContextDiscarded()) {
2424 return;
2425 }
2426
2427 nsAutoCString scheme;
2428 mURI->GetScheme(scheme);
2429 bool isHttp = scheme.EqualsLiteral("http");
2430 if (!isHttp && !scheme.EqualsLiteral("https")) {
2431 return;
2432 }
2433
2434 nsAutoCString altSvc;
2435 Unused << mResponseHead->GetHeader(nsHttp::Alternate_Service, altSvc);
2436 if (altSvc.IsEmpty()) {
2437 return;
2438 }
2439
2440 if (!nsHttp::IsReasonableHeaderValue(altSvc)) {
2441 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)
;
2442 return;
2443 }
2444
2445 nsAutoCString originHost;
2446 int32_t originPort = 80;
2447 mURI->GetPort(&originPort);
2448 if (NS_FAILED(mURI->GetAsciiHost(originHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(mURI->GetAsciiHost
(originHost))), 0)))
) {
2449 return;
2450 }
2451
2452 nsCOMPtr<nsIInterfaceRequestor> callbacks;
2453 nsCOMPtr<nsProxyInfo> proxyInfo;
2454 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
2455 getter_AddRefs(callbacks));
2456
2457 if (mProxyInfo) {
2458 proxyInfo = do_QueryInterface(mProxyInfo);
2459 }
2460
2461 OriginAttributes originAttributes;
2462 // Regular principal in case we have a proxy.
2463 if (proxyInfo &&
2464 !StaticPrefs::privacy_partition_network_state_connection_with_proxy()) {
2465 StoragePrincipalHelper::GetOriginAttributes(
2466 this, originAttributes, StoragePrincipalHelper::eRegularPrincipal);
2467 } else {
2468 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
2469 this, originAttributes);
2470 }
2471
2472 AltSvcMapping::ProcessHeader(
2473 altSvc, scheme, originHost, originPort, mUsername, mPrivateBrowsing,
2474 callbacks, proxyInfo, mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7), originAttributes);
2475}
2476
2477nsresult nsHttpChannel::ProcessResponse() {
2478 uint32_t httpStatus = mResponseHead->Status();
2479
2480 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)
2481 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)
;
2482
2483 // Gather data on whether the transaction and page (if this is
2484 // the initial page load) is being loaded with SSL.
2485 Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_IS_SSL,
2486 mConnectionInfo->EndToEndSSL());
2487 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
2488 Telemetry::Accumulate(Telemetry::HTTP_PAGELOAD_IS_SSL,
2489 mConnectionInfo->EndToEndSSL());
2490 }
2491
2492 if (Telemetry::CanRecordPrereleaseData()) {
2493 // how often do we see something like Alt-Svc: "443:quic,p=1"
2494 // and Alt-Svc: "h3-****"
2495 nsAutoCString alt_service;
2496 Unused << mResponseHead->GetHeader(nsHttp::Alternate_Service, alt_service);
2497 uint32_t saw_quic = 0;
2498 if (!alt_service.IsEmpty()) {
2499 if (strstr(alt_service.get(), "h3-")) {
2500 saw_quic = 1;
2501 } else if (strstr(alt_service.get(), "quic")) {
2502 saw_quic = 2;
2503 }
2504 }
2505 Telemetry::Accumulate(Telemetry::HTTP_SAW_QUIC_ALT_PROTOCOL_2, saw_quic);
2506
2507 // Gather data on various response status to monitor any increased frequency
2508 // of auth failures due to Bug 1896350
2509 switch (httpStatus) {
2510 case 200:
2511 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 0);
2512 mozilla::glean::networking::http_response_status_code.Get("200_ok"_ns)
2513 .Add(1);
2514 break;
2515 case 301:
2516 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 1);
2517 mozilla::glean::networking::http_response_status_code
2518 .Get("301_moved_permanently"_ns)
2519 .Add(1);
2520 break;
2521 case 302:
2522 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 2);
2523 mozilla::glean::networking::http_response_status_code
2524 .Get("302_found"_ns)
2525 .Add(1);
2526 break;
2527 case 304:
2528 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 3);
2529 mozilla::glean::networking::http_response_status_code
2530 .Get("304_not_modified"_ns)
2531 .Add(1);
2532 break;
2533 case 307:
2534 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 4);
2535 mozilla::glean::networking::http_response_status_code
2536 .Get("307_temporary_redirect"_ns)
2537 .Add(1);
2538 break;
2539 case 308:
2540 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 5);
2541 mozilla::glean::networking::http_response_status_code
2542 .Get("308_permanent_redirect"_ns)
2543 .Add(1);
2544 break;
2545 case 400:
2546 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 6);
2547 mozilla::glean::networking::http_response_status_code
2548 .Get("400_bad_request"_ns)
2549 .Add(1);
2550 break;
2551 case 401:
2552 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 7);
2553 mozilla::glean::networking::http_response_status_code
2554 .Get("401_unauthorized"_ns)
2555 .Add(1);
2556 break;
2557 case 403:
2558 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 8);
2559 mozilla::glean::networking::http_response_status_code
2560 .Get("403_forbidden"_ns)
2561 .Add(1);
2562 break;
2563 case 404:
2564 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 9);
2565 mozilla::glean::networking::http_response_status_code
2566 .Get("404_not_found"_ns)
2567 .Add(1);
2568 break;
2569 case 421:
2570 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 11);
2571 mozilla::glean::networking::http_response_status_code
2572 .Get("421_misdirected_request"_ns)
2573 .Add(1);
2574 break;
2575 case 425:
2576 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 11);
2577 mozilla::glean::networking::http_response_status_code
2578 .Get("425_too_early"_ns)
2579 .Add(1);
2580 break;
2581 case 429:
2582 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 11);
2583 mozilla::glean::networking::http_response_status_code
2584 .Get("429_too_many_requests"_ns)
2585 .Add(1);
2586 break;
2587 case 500:
2588 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 10);
2589 mozilla::glean::networking::http_response_status_code
2590 .Get("other_5xx"_ns)
2591 .Add(1);
2592 break;
2593 default:
2594 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_STATUS_CODE, 11);
2595 if (httpStatus >= 400 && httpStatus < 500) {
2596 mozilla::glean::networking::http_response_status_code
2597 .Get("other_4xx"_ns)
2598 .Add(1);
2599 } else if (httpStatus > 500) {
2600 mozilla::glean::networking::http_response_status_code
2601 .Get("other_5xx"_ns)
2602 .Add(1);
2603 } else {
2604 mozilla::glean::networking::http_response_status_code.Get("other"_ns)
2605 .Add(1);
2606 }
2607 break;
2608 }
2609 }
2610
2611 // Let the predictor know whether this was a cacheable response or not so
2612 // that it knows whether or not to possibly prefetch this resource in the
2613 // future.
2614 // We use GetReferringPage because mReferrerInfo may not be set at all(this is
2615 // especially useful in xpcshell tests, where we don't have an actual pageload
2616 // to get a referrer from).
2617 nsCOMPtr<nsIURI> referrer = GetReferringPage();
2618 if (!referrer && mReferrerInfo) {
2619 referrer = mReferrerInfo->GetOriginalReferrer();
2620 }
2621
2622 if (referrer) {
2623 nsCOMPtr<nsILoadContextInfo> lci = GetLoadContextInfo(this);
2624 mozilla::net::Predictor::UpdateCacheability(
2625 referrer, mURI, httpStatus, mRequestHead, mResponseHead.get(), lci,
2626 IsThirdPartyTrackingResource());
2627 }
2628
2629 // Only allow 407 (authentication required) to continue
2630 if (mTransaction && mTransaction->ProxyConnectFailed() && httpStatus != 407) {
2631 return ProcessFailedProxyConnect(httpStatus);
2632 }
2633
2634 MOZ_ASSERT(!mCachedContentIsValid || mRaceCacheWithNetwork,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCachedContentIsValid || mRaceCacheWithNetwork)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mCachedContentIsValid || mRaceCacheWithNetwork))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mCachedContentIsValid || mRaceCacheWithNetwork"
" (" "We should not be hitting the network if we have valid cached "
"content unless we are racing the network and cache" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2636); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachedContentIsValid || mRaceCacheWithNetwork"
") (" "We should not be hitting the network if we have valid cached "
"content unless we are racing the network and cache" ")"); do
{ *((volatile int*)__null) = 2636; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2635 "We should not be hitting the network if we have valid cached "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCachedContentIsValid || mRaceCacheWithNetwork)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mCachedContentIsValid || mRaceCacheWithNetwork))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mCachedContentIsValid || mRaceCacheWithNetwork"
" (" "We should not be hitting the network if we have valid cached "
"content unless we are racing the network and cache" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2636); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachedContentIsValid || mRaceCacheWithNetwork"
") (" "We should not be hitting the network if we have valid cached "
"content unless we are racing the network and cache" ")"); do
{ *((volatile int*)__null) = 2636; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2636 "content unless we are racing the network and cache")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCachedContentIsValid || mRaceCacheWithNetwork)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mCachedContentIsValid || mRaceCacheWithNetwork))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mCachedContentIsValid || mRaceCacheWithNetwork"
" (" "We should not be hitting the network if we have valid cached "
"content unless we are racing the network and cache" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2636); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachedContentIsValid || mRaceCacheWithNetwork"
") (" "We should not be hitting the network if we have valid cached "
"content unless we are racing the network and cache" ")"); do
{ *((volatile int*)__null) = 2636; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2637
2638 ProcessSSLInformation();
2639
2640 // notify "http-on-examine-response" observers
2641 gHttpHandler->OnExamineResponse(this);
2642
2643 return ContinueProcessResponse1();
2644}
2645
2646void nsHttpChannel::AsyncContinueProcessResponse() {
2647 nsresult rv;
2648 rv = ContinueProcessResponse1();
2649 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2650 // A synchronous failure here would normally be passed as the return
2651 // value from OnStartRequest, which would in turn cancel the request.
2652 // If we're continuing asynchronously, we need to cancel the request
2653 // ourselves.
2654 Unused << Cancel(rv);
2655 }
2656}
2657
2658nsresult nsHttpChannel::ContinueProcessResponse1() {
2659 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 2659; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2660 nsresult rv = NS_OK;
2661
2662 if (mSuspendCount) {
2663 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)
2664 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
2665 mCallOnResume = [](nsHttpChannel* self) {
2666 self->AsyncContinueProcessResponse();
2667 return NS_OK;
2668 };
2669 return NS_OK;
2670 }
2671
2672 // Check if request was cancelled during http-on-examine-response.
2673 if (mCanceled) {
2674 return CallOnStartRequest();
2675 }
2676
2677 uint32_t httpStatus = mResponseHead->Status();
2678
2679 // STS, Cookies and Alt-Service should not be handled on proxy failure.
2680 // If proxy CONNECT response needs to complete, wait to process connection
2681 // for Strict-Transport-Security.
2682 if (!(mTransaction && mTransaction->ProxyConnectFailed()) &&
2683 (httpStatus != 407)) {
2684 if (nsAutoCString cookie;
2685 NS_SUCCEEDED(mResponseHead->GetHeader(nsHttp::Set_Cookie, cookie))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Set_Cookie, cookie))), 1)))
) {
2686 SetCookie(cookie);
2687 nsCOMPtr<nsIParentChannel> parentChannel;
2688 NS_QueryNotificationCallbacks(this, parentChannel);
2689 if (RefPtr<HttpChannelParent> httpParent =
2690 do_QueryObject(parentChannel)) {
2691 httpParent->SetCookie(std::move(cookie));
2692 }
2693 }
2694
2695 // Given a successful connection, process any STS or PKP data that's
2696 // relevant.
2697 nsresult rv = ProcessSecurityHeaders();
2698 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2699 NS_WARNING("ProcessSTSHeader failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSTSHeader failed, continuing load."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2699)
;
2700 }
2701
2702 if ((httpStatus < 500) && (httpStatus != 421)) {
2703 ProcessAltService();
2704 }
2705 }
2706
2707 if (LoadConcurrentCacheAccess() && LoadCachedContentIsPartial() &&
2708 httpStatus != 206) {
2709 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
2710 (" 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)
2711 "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)
;
2712 return NS_ERROR_CORRUPTED_CONTENT;
2713 }
2714
2715 // handle unused username and password in url (see bug 232567)
2716 if (httpStatus != 401 && httpStatus != 407) {
2717 if (!mAuthRetryPending) {
2718 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",
"/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2718); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { *((volatile int*)__null) = 2718; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2719 rv = mAuthProvider ? mAuthProvider->CheckForSuperfluousAuth()
2720 : NS_ERROR_UNEXPECTED;
2721 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2722 mStatus = rv;
2723 LOG((" CheckForSuperfluousAuth 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
, " CheckForSuperfluousAuth failed (%08x)", static_cast<uint32_t
>(rv)); } } while (0)
2724 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
, " CheckForSuperfluousAuth failed (%08x)", static_cast<uint32_t
>(rv)); } } while (0)
;
2725 }
2726 }
2727 if (mCanceled) return CallOnStartRequest();
2728
2729 // reset the authentication's current continuation state because ourvr
2730 // last authentication attempt has been completed successfully
2731 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",
"/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2731); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { *((volatile int*)__null) = 2731; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2732 rv = mAuthProvider ? mAuthProvider->Disconnect(NS_ERROR_ABORT)
2733 : NS_ERROR_UNEXPECTED;
2734 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2735 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)
;
2736 }
2737 mAuthProvider = nullptr;
2738 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)
;
2739 }
2740
2741 gHttpHandler->OnAfterExamineResponse(this);
2742
2743 // No process switch needed, continue as normal.
2744 return ContinueProcessResponse2(rv);
2745}
2746
2747nsresult nsHttpChannel::ContinueProcessResponse2(nsresult rv) {
2748 if (mSuspendCount) {
2749 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)
2750 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
2751 mCallOnResume = [rv](nsHttpChannel* self) {
2752 Unused << self->ContinueProcessResponse2(rv);
2753 return NS_OK;
2754 };
2755 return NS_OK;
2756 }
2757
2758 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCanceled) {
2759 // The process switch failed, cancel this channel.
2760 Cancel(rv);
2761 return CallOnStartRequest();
2762 }
2763
2764 if (mAPIRedirectToURI && !mCanceled) {
2765 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2765); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { *((volatile int*)__null) = 2765; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2766 nsCOMPtr<nsIURI> redirectTo;
2767 mAPIRedirectToURI.swap(redirectTo);
2768
2769 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
2770 rv = StartRedirectChannelToURI(redirectTo,
2771 nsIChannelEventSink::REDIRECT_TEMPORARY);
2772 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2773 return NS_OK;
2774 }
2775 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
2776 }
2777
2778 // Hack: ContinueProcessResponse3 uses NS_OK to detect successful
2779 // redirects, so we distinguish this codepath (a non-redirect that's
2780 // processing normally) by passing in a bogus error code.
2781 return ContinueProcessResponse3(NS_BINDING_FAILED);
2782}
2783
2784nsresult nsHttpChannel::ContinueProcessResponse3(nsresult rv) {
2785 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)
2786 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)
;
2787
2788 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2789 // redirectTo() has passed through, we don't want to go on with
2790 // this channel. It will now be canceled by the redirect handling
2791 // code that called this function.
2792 return NS_OK;
2793 }
2794
2795 rv = NS_OK;
2796
2797 uint32_t httpStatus = mResponseHead->Status();
2798 bool transactionRestarted = mTransaction->TakeRestartedState();
2799
2800 // handle different server response categories. Note that we handle
2801 // caching or not caching of error pages in
2802 // nsHttpResponseHead::MustValidate; if you change this switch, update that
2803 // one
2804 switch (httpStatus) {
2805 case 200:
2806 case 203:
2807 // Per RFC 2616, 14.35.2, "A server MAY ignore the Range header".
2808 // So if a server does that and sends 200 instead of 206 that we
2809 // expect, notify our caller.
2810 // However, if we wanted to start from the beginning, let it go through
2811 if (LoadResuming() && mStartPos != 0) {
2812 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)
;
2813 Cancel(NS_ERROR_NOT_RESUMABLE);
2814 rv = CallOnStartRequest();
2815 break;
2816 }
2817 // these can normally be cached
2818 rv = ProcessNormal();
2819 MaybeInvalidateCacheEntryForSubsequentGet();
2820 break;
2821 case 206:
2822 if (LoadCachedContentIsPartial()) { // an internal byte range request...
2823 auto func = [](auto* self, nsresult aRv) {
2824 return self->ContinueProcessResponseAfterPartialContent(aRv);
2825 };
2826 rv = ProcessPartialContent(func);
2827 // Directly call ContinueProcessResponseAfterPartialContent if channel
2828 // is not suspended or ProcessPartialContent throws.
2829 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2830 return ContinueProcessResponseAfterPartialContent(rv);
2831 }
2832 return NS_OK;
2833 } else {
2834 mCacheInputStream.CloseAndRelease();
2835 rv = ProcessNormal();
2836 }
2837 break;
2838 case 301:
2839 case 302:
2840 case 307:
2841 case 308:
2842 case 303:
2843#if 0
2844 case 305: // disabled as a security measure (see bug 187996).
2845#endif
2846 // don't store the response body for redirects
2847 MaybeInvalidateCacheEntryForSubsequentGet();
2848 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
2849 rv = AsyncProcessRedirection(httpStatus);
2850 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2851 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
2852 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)
2853 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)
;
2854 // don't cache failed redirect responses.
2855 if (mCacheEntry) mCacheEntry->AsyncDoom(nullptr);
2856 if (DoNotRender3xxBody(rv)) {
2857 mStatus = rv;
2858 DoNotifyListener();
2859 } else {
2860 rv = ContinueProcessResponse4(rv);
2861 }
2862 }
2863 break;
2864 case 304:
2865 if (!ShouldBypassProcessNotModified()) {
2866 auto func = [](auto* self, nsresult aRv) {
2867 return self->ContinueProcessResponseAfterNotModified(aRv);
2868 };
2869 rv = ProcessNotModified(func);
2870 // Directly call ContinueProcessResponseAfterNotModified if channel
2871 // is not suspended or ProcessNotModified throws.
2872 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2873 return ContinueProcessResponseAfterNotModified(rv);
2874 }
2875 return NS_OK;
2876 }
2877
2878 // Don't cache uninformative 304
2879 if (LoadCustomConditionalRequest()) {
2880 CloseCacheEntry(false);
2881 }
2882
2883 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2884 rv = ProcessNormal();
2885 }
2886 break;
2887 case 401:
2888 case 407:
2889 if (MOZ_UNLIKELY(httpStatus == 407 && transactionRestarted)(__builtin_expect(!!(httpStatus == 407 && transactionRestarted
), 0))
) {
2890 // The transaction has been internally restarted. We want to
2891 // authenticate to the proxy again, so reuse either cached credentials
2892 // or use default credentials for NTLM/Negotiate. This prevents
2893 // considering the previously used credentials as invalid.
2894 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",
"/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2894); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { *((volatile int*)__null) = 2894; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2895 if (!mAuthProvider) {
2896 mStatus = NS_ERROR_UNEXPECTED;
2897 return ProcessNormal();
2898 }
2899 mAuthProvider->ClearProxyIdent();
2900 }
2901 if (!LoadAuthRedirectedChannel() &&
2902 MOZ_UNLIKELY(LoadCustomAuthHeader())(__builtin_expect(!!(LoadCustomAuthHeader()), 0)) && httpStatus == 401) {
2903 // When a custom auth header fails, we don't want to try
2904 // any cached credentials, nor we want to ask the user.
2905 // It's up to the consumer to re-try w/o setting a custom
2906 // auth header if cached credentials should be attempted.
2907 rv = NS_ERROR_FAILURE;
2908 } else if (httpStatus == 401 &&
2909 StaticPrefs::
2910 network_auth_supress_auth_prompt_for_XFO_failures() &&
2911 !nsContentSecurityUtils::CheckCSPFrameAncestorAndXFO(this)) {
2912 // CSP Frame Ancestor and X-Frame-Options check has failed
2913 // Do not prompt http auth - Bug 1629307
2914 rv = NS_ERROR_FAILURE;
2915 } else {
2916 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",
"/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2916); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { *((volatile int*)__null) = 2916; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2917 rv = mAuthProvider
2918 ? mAuthProvider->ProcessAuthentication(
2919 httpStatus, mConnectionInfo->EndToEndSSL() &&
2920 mTransaction &&
2921 mTransaction->ProxyConnectFailed())
2922 : NS_ERROR_UNEXPECTED;
2923 }
2924 if (rv == NS_ERROR_IN_PROGRESS) {
2925 // authentication prompt has been invoked and result
2926 // is expected asynchronously
2927 mIsAuthChannel = true;
2928 mAuthRetryPending = true;
2929 if (httpStatus == 407 ||
2930 (mTransaction && mTransaction->ProxyConnectFailed())) {
2931 StoreProxyAuthPending(true);
2932 }
2933
2934 // suspend the transaction pump to stop receiving the
2935 // unauthenticated content data. We will throw that data
2936 // away when user provides credentials or resume the pump
2937 // when user refuses to authenticate.
2938 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
2939 ("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)
2940 "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)
;
2941 mTransactionPump->Suspend();
2942
2943#ifdef DEBUG1
2944 // This is for test purposes only. See bug 1683176 for details.
2945 gHttpHandler->OnTransactionSuspendedDueToAuthentication(this);
2946#endif
2947 rv = NS_OK;
2948 } else if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2949 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)
2950 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)
;
2951 if (mTransaction && mTransaction->ProxyConnectFailed()) {
2952 return ProcessFailedProxyConnect(httpStatus);
2953 }
2954 if (!mAuthRetryPending) {
2955 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",
"/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 2955); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { *((volatile int*)__null) = 2955; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2956 rv = mAuthProvider ? mAuthProvider->CheckForSuperfluousAuth()
2957 : NS_ERROR_UNEXPECTED;
2958 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2959 mStatus = rv;
2960 LOG(("CheckForSuperfluousAuth 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
, "CheckForSuperfluousAuth failed [rv=%x]\n", static_cast<
uint32_t>(rv)); } } while (0)
2961 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
, "CheckForSuperfluousAuth failed [rv=%x]\n", static_cast<
uint32_t>(rv)); } } while (0)
;
2962 }
2963 }
2964 rv = ProcessNormal();
2965 } else {
2966 mIsAuthChannel = true;
2967 mAuthRetryPending = true;
2968 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
2969 if (NS_SUCCEEDED(RedirectToNewChannelForAuthRetry())((bool)(__builtin_expect(!!(!NS_FAILED_impl(RedirectToNewChannelForAuthRetry
())), 1)))
) {
2970 return NS_OK;
2971 }
2972 mAuthRetryPending = false;
2973 rv = ProcessNormal();
2974 }
2975 }
2976 break;
2977
2978 case 408:
2979 case 425:
2980 case 429:
2981 // Do not cache 408, 425 and 429.
2982 CloseCacheEntry(false);
2983 [[fallthrough]]; // process normally
2984 default:
2985 rv = ProcessNormal();
2986 MaybeInvalidateCacheEntryForSubsequentGet();
2987 break;
2988 }
2989
2990 UpdateCacheDisposition(false, false);
2991 return rv;
2992}
2993
2994nsresult nsHttpChannel::ContinueProcessResponseAfterPartialContent(
2995 nsresult aRv) {
2996 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
2997 ("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)
2998 "[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)
2999 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)
;
3000
3001 UpdateCacheDisposition(false, NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1))));
3002 return aRv;
3003}
3004
3005nsresult nsHttpChannel::ContinueProcessResponseAfterNotModified(nsresult aRv) {
3006 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
3007 ("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)
3008 "[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)
3009 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)
;
3010
3011 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))) {
3012 StoreTransactionReplaced(true);
3013 UpdateCacheDisposition(true, false);
3014 return NS_OK;
3015 }
3016
3017 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)
3018 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)
;
3019
3020 // We cannot read from the cache entry, it might be in an
3021 // incosistent state. Doom it and redirect the channel
3022 // to the same URI to reload from the network.
3023 mCacheInputStream.CloseAndRelease();
3024 if (mCacheEntry) {
3025 mCacheEntry->AsyncDoom(nullptr);
3026 mCacheEntry = nullptr;
3027 }
3028
3029 nsresult rv =
3030 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
3031 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3032 return NS_OK;
3033 }
3034
3035 // Don't cache uninformative 304
3036 if (LoadCustomConditionalRequest()) {
3037 CloseCacheEntry(false);
3038 }
3039
3040 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3041 rv = ProcessNormal();
3042 }
3043
3044 UpdateCacheDisposition(false, false);
3045 return rv;
3046}
3047
3048static void ReportHttpResponseVersion(HttpVersion version) {
3049 if (Telemetry::CanRecordPrereleaseData()) {
3050 Telemetry::Accumulate(Telemetry::HTTP_RESPONSE_VERSION,
3051 static_cast<uint32_t>(version));
3052 }
3053 mozilla::glean::networking::http_response_version
3054 .Get(HttpVersionToTelemetryLabel(version))
3055 .Add(1);
3056}
3057
3058void nsHttpChannel::UpdateCacheDisposition(bool aSuccessfulReval,
3059 bool aPartialContentUsed) {
3060 if (mRaceDelay && !mRaceCacheWithNetwork &&
3061 (LoadCachedContentIsPartial() || mDidReval)) {
3062 if (aSuccessfulReval || aPartialContentUsed) {
3063 AccumulateCategorical(
3064 Telemetry::LABELS_NETWORK_RACE_CACHE_VALIDATION::CachedContentUsed);
3065 } else {
3066 AccumulateCategorical(Telemetry::LABELS_NETWORK_RACE_CACHE_VALIDATION::
3067 CachedContentNotUsed);
3068 }
3069 }
3070
3071 if (Telemetry::CanRecordPrereleaseData()) {
3072 CacheDisposition cacheDisposition;
3073 if (!mDidReval) {
3074 cacheDisposition = kCacheMissed;
3075 } else if (aSuccessfulReval) {
3076 cacheDisposition = kCacheHitViaReval;
3077 } else {
3078 cacheDisposition = kCacheMissedViaReval;
3079 }
3080 AccumulateCacheHitTelemetry(cacheDisposition, this);
3081 mCacheDisposition = cacheDisposition;
3082 }
3083
3084 ReportHttpResponseVersion(mResponseHead->Version());
3085}
3086
3087nsresult nsHttpChannel::ContinueProcessResponse4(nsresult rv) {
3088 bool doNotRender = DoNotRender3xxBody(rv);
3089
3090 if (rv == NS_ERROR_DOM_BAD_URI && mRedirectURI) {
3091 bool isHTTP =
3092 mRedirectURI->SchemeIs("http") || mRedirectURI->SchemeIs("https");
3093 if (!isHTTP) {
3094 // This was a blocked attempt to redirect and subvert the system by
3095 // redirecting to another protocol (perhaps javascript:)
3096 // In that case we want to throw an error instead of displaying the
3097 // non-redirected response body.
3098 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)
;
3099 doNotRender = true;
3100 rv = NS_ERROR_CORRUPTED_CONTENT;
3101 }
3102 }
3103
3104 if (doNotRender) {
3105 Cancel(rv);
3106 DoNotifyListener();
3107 return rv;
3108 }
3109
3110 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3111 UpdateInhibitPersistentCachingFlag();
3112
3113 MaybeCreateCacheEntryWhenRCWN();
3114
3115 rv = InitCacheEntry();
3116 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3117 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
3118 ("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)
3119 "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)
3120 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)
;
3121 }
3122 CloseCacheEntry(false);
3123 return NS_OK;
3124 }
3125
3126 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)
3127 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)
;
3128 if (mTransaction && mTransaction->ProxyConnectFailed()) {
3129 return ProcessFailedProxyConnect(mRedirectType);
3130 }
3131 return ProcessNormal();
3132}
3133
3134nsresult nsHttpChannel::ProcessNormal() {
3135 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)
;
3136
3137 return ContinueProcessNormal(NS_OK);
3138}
3139
3140nsresult nsHttpChannel::ContinueProcessNormal(nsresult rv) {
3141 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)
;
3142
3143 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3144 // Fill the failure status here, we have failed to fall back, thus we
3145 // have to report our status as failed.
3146 mStatus = rv;
3147 DoNotifyListener();
3148 return rv;
3149 }
3150
3151 rv = ProcessCrossOriginSecurityHeaders();
3152 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3153 mStatus = rv;
3154 HandleAsyncAbort();
3155 return rv;
3156 }
3157
3158 // if we're here, then any byte-range requests failed to result in a partial
3159 // response. we must clear this flag to prevent BufferPartialContent from
3160 // being called inside our OnDataAvailable (see bug 136678).
3161 StoreCachedContentIsPartial(false);
3162
3163 UpdateInhibitPersistentCachingFlag();
3164
3165 MaybeCreateCacheEntryWhenRCWN();
3166
3167 // this must be called before firing OnStartRequest, since http clients,
3168 // such as imagelib, expect our cache entry to already have the correct
3169 // expiration time (bug 87710).
3170 if (mCacheEntry) {
3171 rv = InitCacheEntry();
3172 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CloseCacheEntry(true);
3173 }
3174
3175 // Check that the server sent us what we were asking for
3176 if (LoadResuming()) {
3177 // Create an entity id from the response
3178 nsAutoCString id;
3179 rv = GetEntityID(id);
3180 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3181 // If creating an entity id is not possible -> error
3182 Cancel(NS_ERROR_NOT_RESUMABLE);
3183 } else if (mResponseHead->Status() != 206 &&
3184 mResponseHead->Status() != 200) {
3185 // Probably 404 Not Found, 412 Precondition Failed or
3186 // 416 Invalid Range -> error
3187 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)
3188 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3189 Cancel(NS_ERROR_ENTITY_CHANGED);
3190 }
3191 // If we were passed an entity id, verify it's equal to the server's
3192 else if (!mEntityID.IsEmpty()) {
3193 if (!mEntityID.Equals(id)) {
3194 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)
3195 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)
;
3196 Cancel(NS_ERROR_ENTITY_CHANGED);
3197 }
3198 }
3199 }
3200
3201 rv = CallOnStartRequest();
3202 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3203
3204 // install cache listener if we still have a cache entry open
3205 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3206 rv = InstallCacheListener();
3207 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3208 }
3209
3210 return NS_OK;
3211}
3212
3213nsresult nsHttpChannel::PromptTempRedirect() {
3214 if (!gHttpHandler->PromptTempRedirect()) {
3215 return NS_OK;
3216 }
3217 nsresult rv;
3218 nsCOMPtr<nsIStringBundleService> bundleService;
3219 bundleService = mozilla::components::StringBundle::Service(&rv);
3220 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3221
3222 nsCOMPtr<nsIStringBundle> stringBundle;
3223 rv =
3224 bundleService->CreateBundle(NECKO_MSGS_URL"chrome://necko/locale/necko.properties", getter_AddRefs(stringBundle));
3225 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3226
3227 nsAutoString messageString;
3228 rv = stringBundle->GetStringFromName("RepostFormData", messageString);
3229 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3230 bool repost = false;
3231
3232 nsCOMPtr<nsIPrompt> prompt;
3233 GetCallback(prompt);
3234 if (!prompt) return NS_ERROR_NO_INTERFACE;
3235
3236 prompt->Confirm(nullptr, messageString.get(), &repost);
3237 if (!repost) return NS_ERROR_FAILURE;
3238 }
3239
3240 return rv;
3241}
3242
3243nsresult nsHttpChannel::ProxyFailover() {
3244 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)
;
3245
3246 nsresult rv;
3247
3248 nsCOMPtr<nsIProtocolProxyService> pps;
3249 pps = mozilla::components::ProtocolProxy::Service(&rv);
3250 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3251
3252 nsCOMPtr<nsIProxyInfo> pi;
3253 rv = pps->GetFailoverForProxy(mConnectionInfo->ProxyInfo(), mURI, mStatus,
3254 getter_AddRefs(pi));
3255#ifdef MOZ_PROXY_DIRECT_FAILOVER1
3256 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3257 if (!StaticPrefs::network_proxy_failover_direct()) {
3258 return rv;
3259 }
3260 // If this request used a failed proxy and there is no failover available,
3261 // fallback to DIRECT connections for conservative requests.
3262 if (LoadBeConservative()) {
3263 rv = pps->NewProxyInfo("direct"_ns, ""_ns, 0, ""_ns, ""_ns, 0, UINT32_MAX(4294967295U),
3264 nullptr, getter_AddRefs(pi));
3265 }
3266#endif
3267 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3268 return rv;
3269 }
3270#ifdef MOZ_PROXY_DIRECT_FAILOVER1
3271 }
3272#endif
3273
3274 // XXXbz so where does this codepath remove us from the loadgroup,
3275 // exactly?
3276 return AsyncDoReplaceWithProxy(pi);
3277}
3278
3279void nsHttpChannel::SetHTTPSSVCRecord(
3280 already_AddRefed<nsIDNSHTTPSSVCRecord>&& aRecord) {
3281 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)
;
3282 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
3283 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mHTTPSSVCRecord"
")"); do { *((volatile int*)__null) = 3283; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3284 mHTTPSSVCRecord.emplace(std::move(record));
3285}
3286
3287void nsHttpChannel::HandleAsyncRedirectChannelToHttps() {
3288 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 3288; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3289
3290 if (mSuspendCount) {
3291 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)
3292 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3293 mCallOnResume = [](nsHttpChannel* self) {
3294 self->HandleAsyncRedirectChannelToHttps();
3295 return NS_OK;
3296 };
3297 return;
3298 }
3299
3300 nsresult rv = StartRedirectChannelToHttps();
3301 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3302 rv = ContinueAsyncRedirectChannelToURI(rv);
3303 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3304 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)
3305 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)
;
3306 }
3307 }
3308}
3309
3310nsresult nsHttpChannel::StartRedirectChannelToHttps() {
3311 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)
;
3312
3313 nsCOMPtr<nsIURI> upgradedURI;
3314 nsresult rv = NS_GetSecureUpgradedURI(mURI, getter_AddRefs(upgradedURI));
3315 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3315); return rv; } } while (false)
;
3316
3317 return StartRedirectChannelToURI(
3318 upgradedURI, nsIChannelEventSink::REDIRECT_PERMANENT |
3319 nsIChannelEventSink::REDIRECT_STS_UPGRADE);
3320}
3321
3322void nsHttpChannel::HandleAsyncAPIRedirect() {
3323 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 3323; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3324 MOZ_ASSERT(mAPIRedirectToURI, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAPIRedirectToURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAPIRedirectToURI))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mAPIRedirectToURI"
" (" "How did that happen?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectToURI"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 3324; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3325
3326 if (mSuspendCount) {
3327 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)
;
3328 mCallOnResume = [](nsHttpChannel* self) {
3329 self->HandleAsyncAPIRedirect();
3330 return NS_OK;
3331 };
3332 return;
3333 }
3334
3335 nsresult rv = StartRedirectChannelToURI(
3336 mAPIRedirectToURI, nsIChannelEventSink::REDIRECT_PERMANENT);
3337 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3338 rv = ContinueAsyncRedirectChannelToURI(rv);
3339 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3340 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)
3341 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)
;
3342 }
3343 }
3344}
3345
3346void nsHttpChannel::HandleAsyncRedirectToUnstrippedURI() {
3347 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 3347; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3348
3349 if (mSuspendCount) {
3350 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
3351 ("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)
3352 "[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)
3353 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3354 mCallOnResume = [](nsHttpChannel* self) {
3355 self->HandleAsyncRedirectToUnstrippedURI();
3356 return NS_OK;
3357 };
3358 return;
3359 }
3360
3361 nsCOMPtr<nsIURI> unstrippedURI;
3362 mLoadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
3363
3364 // Clear the unstripped URI from the loadInfo before starting redirect in case
3365 // endless redirect.
3366 mLoadInfo->SetUnstrippedURI(nullptr);
3367
3368 nsresult rv = StartRedirectChannelToURI(
3369 unstrippedURI, nsIChannelEventSink::REDIRECT_PERMANENT);
3370
3371 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3372 rv = ContinueAsyncRedirectChannelToURI(rv);
3373 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3374 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)
3375 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)
;
3376 }
3377 }
3378}
3379nsresult nsHttpChannel::RedirectToNewChannelForAuthRetry() {
3380 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)
;
3381 nsresult rv = NS_OK;
3382
3383 nsCOMPtr<nsILoadInfo> redirectLoadInfo = CloneLoadInfoForRedirect(
3384 mURI, nsIChannelEventSink::REDIRECT_INTERNAL |
3385 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
3386
3387 nsCOMPtr<nsIIOService> ioService;
3388
3389 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
3390 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3390); return rv; } } while (false)
;
3391
3392 nsCOMPtr<nsIChannel> newChannel;
3393 rv = gHttpHandler->NewProxiedChannel(mURI, mProxyInfo, mProxyResolveFlags,
3394 mProxyURI, mLoadInfo,
3395 getter_AddRefs(newChannel));
3396
3397 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3397); return rv; } } while (false)
;
3398
3399 rv = SetupReplacementChannel(mURI, newChannel, true,
3400 nsIChannelEventSink::REDIRECT_INTERNAL |
3401 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
3402 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3402); return rv; } } while (false)
;
3403
3404 // rewind the upload stream
3405 if (mUploadStream) {
3406 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
3407 nsresult rv = NS_ERROR_NO_INTERFACE;
3408 if (seekable) {
3409 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
3410 }
3411
3412 // This should not normally happen, but it's possible that big memory
3413 // blobs originating in the other process can't be rewinded.
3414 // In that case we just fail the request, otherwise the content length
3415 // will not match and this load will never complete.
3416 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3416); return rv; } } while (false)
;
3417 }
3418
3419 RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel);
3420
3421 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",
"/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthProvider"
")"); do { *((volatile int*)__null) = 3421; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3422 httpChannelImpl->mAuthProvider = std::move(mAuthProvider);
3423
3424 httpChannelImpl->mProxyInfo = mProxyInfo;
3425
3426 if ((mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) ||
3427 mTransaction->HasStickyConnection()) {
3428 mConnectionInfo = mTransaction->GetConnInfo();
3429
3430 httpChannelImpl->mTransactionSticky = mTransaction;
3431
3432 if (mTransaction->Http2Disabled()) {
3433 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
3434 }
3435 if (mTransaction->Http3Disabled()) {
3436 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
3437 }
3438 }
3439 httpChannelImpl->mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
3440 if (LoadAuthConnectionRestartable()) {
3441 httpChannelImpl->mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
3442 } else {
3443 httpChannelImpl->mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
3444 }
3445
3446 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3446); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo"
")"); do { *((volatile int*)__null) = 3446; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3447 httpChannelImpl->mConnectionInfo = mConnectionInfo->Clone();
3448
3449 // we need to store the state to skip unnecessary checks in the new channel
3450 httpChannelImpl->StoreAuthRedirectedChannel(true);
3451
3452 // We must copy proxy and auth header to the new channel.
3453 // Although the new channel can populate auth headers from auth cache, we
3454 // would still like to use the auth headers generated in this channel. The
3455 // main reason for doing this is that certain connection-based/stateful auth
3456 // schemes like NTLM will fail when we try generate the credentials more than
3457 // the number of times the server has presented us the challenge due to the
3458 // usage of nonce in generating the credentials Copying the auth header will
3459 // bypass generation of the credentials
3460 nsAutoCString authVal;
3461 if (NS_SUCCEEDED(GetRequestHeader("Proxy-Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Proxy-Authorization"_ns, authVal))), 1)))
) {
3462 httpChannelImpl->SetRequestHeader("Proxy-Authorization"_ns, authVal, false);
3463 }
3464 if (NS_SUCCEEDED(GetRequestHeader("Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Authorization"_ns, authVal))), 1)))
) {
3465 httpChannelImpl->SetRequestHeader("Authorization"_ns, authVal, false);
3466 }
3467
3468 httpChannelImpl->SetBlockAuthPrompt(LoadBlockAuthPrompt());
3469 mRedirectChannel = newChannel;
3470
3471 rv = gHttpHandler->AsyncOnChannelRedirect(
3472 this, newChannel,
3473 nsIChannelEventSink::REDIRECT_INTERNAL |
3474 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
3475
3476 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
3477
3478 // redirected channel will be opened after we receive the OnStopRequest
3479
3480 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3481 AutoRedirectVetoNotifier notifier(this, rv);
3482 mRedirectChannel = nullptr;
3483 }
3484
3485 return rv;
3486}
3487nsresult nsHttpChannel::StartRedirectChannelToURI(nsIURI* upgradedURI,
3488 uint32_t flags) {
3489 nsresult rv = NS_OK;
3490 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)
;
3491
3492 nsCOMPtr<nsIChannel> newChannel;
3493 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
3494 CloneLoadInfoForRedirect(upgradedURI, flags);
3495
3496 nsCOMPtr<nsIIOService> ioService;
3497 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
3498 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3498); return rv; } } while (false)
;
3499
3500 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), upgradedURI,
3501 redirectLoadInfo,
3502 nullptr, // PerformanceStorage
3503 nullptr, // aLoadGroup
3504 nullptr, // aCallbacks
3505 nsIRequest::LOAD_NORMAL, ioService);
3506 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3506); return rv; } } while (false)
;
3507
3508 rv = SetupReplacementChannel(upgradedURI, newChannel, true, flags);
3509 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3509); return rv; } } while (false)
;
3510
3511 if (mHTTPSSVCRecord) {
3512 RefPtr<nsHttpChannel> httpChan = do_QueryObject(newChannel);
3513 nsCOMPtr<nsIDNSHTTPSSVCRecord> rec = mHTTPSSVCRecord.ref();
3514 if (httpChan && rec) {
3515 httpChan->SetHTTPSSVCRecord(rec.forget());
3516 }
3517 }
3518
3519 // Inform consumers about this fake redirect
3520 mRedirectChannel = newChannel;
3521
3522 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
3523 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
3524
3525 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
3526
3527 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3528 AutoRedirectVetoNotifier notifier(this, rv);
3529
3530 /* Remove the async call to ContinueAsyncRedirectChannelToURI().
3531 * It is called directly by our callers upon return (to clean up
3532 * the failed redirect). */
3533 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
3534 }
3535
3536 return rv;
3537}
3538
3539nsresult nsHttpChannel::ContinueAsyncRedirectChannelToURI(nsresult rv) {
3540 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)
;
3541
3542 // Since we handle mAPIRedirectToURI also after on-examine-response handler
3543 // rather drop it here to avoid any redirect loops, even just hypothetical.
3544 mAPIRedirectToURI = nullptr;
3545
3546 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3547 rv = OpenRedirectChannel(rv);
3548 }
3549
3550 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3551 // Cancel the channel here, the update to https had been vetoed
3552 // but from the security reasons we have to discard the whole channel
3553 // load.
3554 Cancel(rv);
3555 }
3556
3557 if (mLoadGroup) {
3558 mLoadGroup->RemoveRequest(this, nullptr, mStatus);
3559 }
3560
3561 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCachePump && !mTransactionPump) {
3562 // We have to manually notify the listener because there is not any pump
3563 // that would call our OnStart/StopRequest after resume from waiting for
3564 // the redirect callback.
3565 DoNotifyListener();
3566 }
3567
3568 return rv;
3569}
3570
3571nsresult nsHttpChannel::OpenRedirectChannel(nsresult rv) {
3572 AutoRedirectVetoNotifier notifier(this, rv);
3573
3574 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3575
3576 if (!mRedirectChannel) {
3577 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
3578 "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)
;
3579 return NS_ERROR_FAILURE;
3580 }
3581
3582 // Make sure to do this after we received redirect veto answer,
3583 // i.e. after all sinks had been notified
3584 mRedirectChannel->SetOriginalURI(mOriginalURI);
3585
3586 // open new channel
3587 rv = mRedirectChannel->AsyncOpen(mListener);
3588
3589 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3589); return rv; } } while (false)
;
3590
3591 mStatus = NS_BINDING_REDIRECTED;
3592
3593 notifier.RedirectSucceeded();
3594
3595 ReleaseListeners();
3596
3597 return NS_OK;
3598}
3599
3600nsresult nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi) {
3601 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)
;
3602 nsresult rv;
3603
3604 nsCOMPtr<nsIChannel> newChannel;
3605 rv = gHttpHandler->NewProxiedChannel(mURI, pi, mProxyResolveFlags, mProxyURI,
3606 mLoadInfo, getter_AddRefs(newChannel));
3607 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3608
3609 uint32_t flags = nsIChannelEventSink::REDIRECT_INTERNAL;
3610
3611 rv = SetupReplacementChannel(mURI, newChannel, true, flags);
3612 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3613
3614 // Inform consumers about this fake redirect
3615 mRedirectChannel = newChannel;
3616
3617 PushRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
3618 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
3619
3620 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
3621
3622 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3623 AutoRedirectVetoNotifier notifier(this, rv);
3624 PopRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
3625 }
3626
3627 return rv;
3628}
3629
3630nsresult nsHttpChannel::ResolveProxy() {
3631 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)
;
3632
3633 nsresult rv;
3634
3635 nsCOMPtr<nsIProtocolProxyService> pps;
3636 pps = mozilla::components::ProtocolProxy::Service(&rv);
3637 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3638
3639 // using the nsIProtocolProxyService2 allows a minor performance
3640 // optimization, but if an add-on has only provided the original interface
3641 // then it is ok to use that version.
3642 nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
3643 if (pps2) {
3644 rv = pps2->AsyncResolve2(this, mProxyResolveFlags, this, nullptr,
3645 getter_AddRefs(mProxyRequest));
3646 } else {
3647 rv = pps->AsyncResolve(static_cast<nsIChannel*>(this), mProxyResolveFlags,
3648 this, nullptr, getter_AddRefs(mProxyRequest));
3649 }
3650
3651 return rv;
3652}
3653
3654bool nsHttpChannel::ResponseWouldVary(nsICacheEntry* entry) {
3655 nsresult rv;
3656 nsAutoCString buf, metaKey;
3657 Unused << mCachedResponseHead->GetHeader(nsHttp::Vary, buf);
3658
3659 constexpr auto prefix = "request-"_ns;
3660
3661 // enumerate the elements of the Vary header...
3662 for (const nsACString& token :
3663 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
3664 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
3665 ("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)
3666 "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)
3667 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)
;
3668 //
3669 // if "*", then assume response would vary. technically speaking,
3670 // "Vary: header, *" is not permitted, but we allow it anyways.
3671 //
3672 // We hash values of cookie-headers for the following reasons:
3673 //
3674 // 1- cookies can be very large in size
3675 //
3676 // 2- cookies may contain sensitive information. (for parity with
3677 // out policy of not storing Set-cookie headers in the cache
3678 // meta data, we likewise do not want to store cookie headers
3679 // here.)
3680 //
3681 if (token.EqualsLiteral("*")) {
3682 return true; // if we encounter this, just get out of here
3683 }
3684
3685 // build cache meta data key...
3686 metaKey = prefix + token;
3687
3688 // check the last value of the given request header to see if it has
3689 // since changed. if so, then indeed the cached response is invalid.
3690 nsCString lastVal;
3691 entry->GetMetaDataElement(metaKey.get(), getter_Copies(lastVal));
3692 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
3693 ("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)
3694 "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)
3695 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)
;
3696
3697 // Look for value of "Cookie" in the request headers
3698 nsHttpAtom atom = nsHttp::ResolveAtom(token);
3699 nsAutoCString newVal;
3700 bool hasHeader = NS_SUCCEEDED(mRequestHead.GetHeader(atom, newVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(atom, newVal))), 1)))
;
3701 if (!lastVal.IsEmpty()) {
3702 // value for this header in cache, but no value in request
3703 if (!hasHeader) {
3704 return true; // yes - response would vary
3705 }
3706
3707 // If this is a cookie-header, stored metadata is not
3708 // the value itself but the hash. So we also hash the
3709 // outgoing value here in order to compare the hashes
3710 nsAutoCString hash;
3711 if (atom == nsHttp::Cookie) {
3712 rv = Hash(newVal.get(), hash);
3713 // If hash failed, be conservative (the cached hash
3714 // exists at this point) and claim response would vary
3715 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return true;
3716 newVal = hash;
3717
3718 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
3719 ("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)
3720 "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)
3721 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)
;
3722 }
3723
3724 if (!newVal.Equals(lastVal)) {
3725 return true; // yes, response would vary
3726 }
3727
3728 } else if (hasHeader) { // old value is empty, but newVal is set
3729 return true;
3730 }
3731 }
3732
3733 return false;
3734}
3735
3736// We need to have an implementation of this function just so that we can keep
3737// all references to mCallOnResume of type nsHttpChannel: it's not OK in C++
3738// to set a member function ptr to a base class function.
3739void nsHttpChannel::HandleAsyncAbort() {
3740 HttpAsyncAborter<nsHttpChannel>::HandleAsyncAbort();
3741}
3742
3743//-----------------------------------------------------------------------------
3744// nsHttpChannel <byte-range>
3745//-----------------------------------------------------------------------------
3746
3747bool nsHttpChannel::IsResumable(int64_t partialLen, int64_t contentLength,
3748 bool ignoreMissingPartialLen) const {
3749 bool hasContentEncoding =
3750 mCachedResponseHead->HasHeader(nsHttp::Content_Encoding);
3751
3752 nsAutoCString etag;
3753 Unused << mCachedResponseHead->GetHeader(nsHttp::ETag, etag);
3754 bool hasWeakEtag = !etag.IsEmpty() && StringBeginsWith(etag, "W/"_ns);
3755
3756 return (partialLen < contentLength) &&
3757 (partialLen > 0 || ignoreMissingPartialLen) && !hasContentEncoding &&
3758 !hasWeakEtag && mCachedResponseHead->IsResumable() &&
3759 !LoadCustomConditionalRequest() && !mCachedResponseHead->NoStore();
3760}
3761
3762nsresult nsHttpChannel::MaybeSetupByteRangeRequest(
3763 int64_t partialLen, int64_t contentLength, bool ignoreMissingPartialLen) {
3764 // Be pesimistic
3765 StoreIsPartialRequest(false);
3766
3767 if (!IsResumable(partialLen, contentLength, ignoreMissingPartialLen)) {
3768 return NS_ERROR_NOT_RESUMABLE;
3769 }
3770
3771 // looks like a partial entry we can reuse; add If-Range
3772 // and Range headers.
3773 nsresult rv = SetupByteRangeRequest(partialLen);
3774 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3775 // Make the request unconditional again.
3776 UntieByteRangeRequest();
3777 }
3778
3779 return rv;
3780}
3781
3782nsresult nsHttpChannel::SetupByteRangeRequest(int64_t partialLen) {
3783 // cached content has been found to be partial, add necessary request
3784 // headers to complete cache entry.
3785
3786 // use strongest validator available...
3787 nsAutoCString val;
3788 Unused << mCachedResponseHead->GetHeader(nsHttp::ETag, val);
3789 if (val.IsEmpty()) {
3790 Unused << mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
3791 }
3792 if (val.IsEmpty()) {
3793 // if we hit this code it means mCachedResponseHead->IsResumable() is
3794 // either broken or not being called.
3795 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no cache validator" ")"); do { *
((volatile int*)__null) = 3795; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
3796 StoreIsPartialRequest(false);
3797 return NS_ERROR_FAILURE;
3798 }
3799
3800 char buf[64];
3801 SprintfLiteral(buf, "bytes=%" PRId64"l" "d" "-", partialLen);
3802
3803 DebugOnly<nsresult> rv{};
3804 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(buf));
3805 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 3805; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3806 rv = mRequestHead.SetHeader(nsHttp::If_Range, val);
3807 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 3807; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3808 StoreIsPartialRequest(true);
3809
3810 return NS_OK;
3811}
3812
3813void nsHttpChannel::UntieByteRangeRequest() {
3814 DebugOnly<nsresult> rv{};
3815 rv = mRequestHead.ClearHeader(nsHttp::Range);
3816 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 3816; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3817 rv = mRequestHead.ClearHeader(nsHttp::If_Range);
3818 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 3818; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3819}
3820
3821nsresult nsHttpChannel::ProcessPartialContent(
3822 const std::function<nsresult(nsHttpChannel*, nsresult)>&
3823 aContinueProcessResponseFunc) {
3824 // ok, we've just received a 206
3825 //
3826 // we need to stream whatever data is in the cache out first, and then
3827 // pick up whatever data is on the wire, writing it into the cache.
3828
3829 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)
;
3830
3831 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3831); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
3832 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3832); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
3833
3834 // Check if the content-encoding we now got is different from the one we
3835 // got before
3836 nsAutoCString contentEncoding, cachedContentEncoding;
3837 // It is possible that there is not such headers
3838 Unused << mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
3839 Unused << mCachedResponseHead->GetHeader(nsHttp::Content_Encoding,
3840 cachedContentEncoding);
3841 if (nsCRT::strcasecmp(contentEncoding.get(), cachedContentEncoding.get()) !=
3842 0) {
3843 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
3844 return CallOnStartRequest();
3845 }
3846
3847 nsresult rv;
3848
3849 int64_t cachedContentLength = mCachedResponseHead->ContentLength();
3850 int64_t entitySize = mResponseHead->TotalEntitySize();
3851
3852 nsAutoCString contentRange;
3853 Unused << mResponseHead->GetHeader(nsHttp::Content_Range, contentRange);
3854 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
3855 ("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)
3856 "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)
3857 ", 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)
3858 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)
3859 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)
;
3860
3861 if ((entitySize >= 0) && (cachedContentLength >= 0) &&
3862 (entitySize != cachedContentLength)) {
3863 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
3864 ("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)
3865 "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)
3866 "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)
3867 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
3868
3869 mCacheEntry->AsyncDoom(nullptr);
3870 Cancel(NS_ERROR_CORRUPTED_CONTENT);
3871 return CallOnStartRequest();
3872 }
3873
3874 if (LoadConcurrentCacheAccess()) {
3875 // We started to read cached data sooner than its write has been done.
3876 // But the concurrent write has not finished completely, so we had to
3877 // do a range request. Now let the content coming from the network
3878 // be presented to consumers and also stored to the cache entry.
3879
3880 rv = InstallCacheListener(mLogicalOffset);
3881 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3882 } else {
3883 // suspend the current transaction
3884 rv = mTransactionPump->Suspend();
3885 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3886 }
3887
3888 // merge any new headers with the cached response headers
3889 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
3890
3891 // update the cached response head
3892 nsAutoCString head;
3893 mCachedResponseHead->Flatten(head, true);
3894 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
3895 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3896
3897 // make the cached response be the current response
3898 mResponseHead = std::move(mCachedResponseHead);
3899
3900 UpdateInhibitPersistentCachingFlag();
3901
3902 rv = UpdateExpirationTime();
3903 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3904
3905 // notify observers interested in looking at a response that has been
3906 // merged with any cached headers (http-on-examine-merged-response).
3907 gHttpHandler->OnExamineMergedResponse(this);
3908
3909 if (LoadConcurrentCacheAccess()) {
3910 StoreCachedContentIsPartial(false);
3911 // Leave the ConcurrentCacheAccess flag set, we want to use it
3912 // to prevent duplicate OnStartRequest call on the target listener
3913 // in case this channel is canceled before it gets its OnStartRequest
3914 // from the http transaction.
3915 return rv;
3916 }
3917
3918 // Now we continue reading the network response.
3919 // the cached content is valid, although incomplete.
3920 mCachedContentIsValid = true;
3921 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
3922 nsresult rv = self->ReadFromCache();
3923 return aContinueProcessResponseFunc(self, rv);
3924 });
3925}
3926
3927nsresult nsHttpChannel::OnDoneReadingPartialCacheEntry(bool* streamDone) {
3928 nsresult rv;
3929
3930 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)
;
3931
3932 // by default, assume we would have streamed all data or failed...
3933 *streamDone = true;
3934
3935 // setup cache listener to append to cache entry
3936 int64_t size;
3937 rv = mCacheEntry->GetDataSize(&size);
3938 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3939
3940 rv = InstallCacheListener(size);
3941 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3942
3943 // Entry is valid, do it now, after the output stream has been opened,
3944 // otherwise when done earlier, pending readers would consider the cache
3945 // entry still as partial (CacheEntry::GetDataSize would return the partial
3946 // data size) and consumers would do the conditional request again.
3947 rv = mCacheEntry->SetValid();
3948 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3949
3950 // need to track the logical offset of the data being sent to our listener
3951 mLogicalOffset = size;
3952
3953 // we're now completing the cached content, so we can clear this flag.
3954 // this puts us in the state of a regular download.
3955 StoreCachedContentIsPartial(false);
3956 // The cache input stream pump is finished, we do not need it any more.
3957 // (see bug 1313923)
3958 mCachePump = nullptr;
3959
3960 // resume the transaction if it exists, otherwise the pipe contained the
3961 // remaining part of the document and we've now streamed all of the data.
3962 if (mTransactionPump) {
3963 rv = mTransactionPump->Resume();
3964 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) *streamDone = false;
3965 } else {
3966 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 3966); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no transaction" ")"); do { *((volatile
int*)__null) = 3966; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3967 }
3968 return rv;
3969}
3970
3971//-----------------------------------------------------------------------------
3972// nsHttpChannel <cache>
3973//-----------------------------------------------------------------------------
3974
3975bool nsHttpChannel::ShouldBypassProcessNotModified() {
3976 if (LoadCustomConditionalRequest()) {
3977 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)
;
3978 return true;
3979 }
3980
3981 if (!mDidReval) {
3982 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
3983 ("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)
3984 "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)
;
3985 return true;
3986 }
3987
3988 return false;
3989}
3990
3991nsresult nsHttpChannel::ProcessNotModified(
3992 const std::function<nsresult(nsHttpChannel*, nsresult)>&
3993 aContinueProcessResponseFunc) {
3994 nsresult rv;
3995
3996 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)
;
3997
3998 // Assert ShouldBypassProcessNotModified() has been checked before call to
3999 // ProcessNotModified().
4000 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()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4000); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ShouldBypassProcessNotModified()"
")"); do { *((volatile int*)__null) = 4000; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4001
4002 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedResponseHead"
")"); do { *((volatile int*)__null) = 4002; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4003 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4003); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { *((volatile int*)__null) = 4003; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4004 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
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4004); return NS_ERROR_UNEXPECTED; } } while (false)
;
4005
4006 // If the 304 response contains a Last-Modified different than the
4007 // one in our cache that is pretty suspicious and is, in at least the
4008 // case of bug 716840, a sign of the server having previously corrupted
4009 // our cache with a bad response. Take the minor step here of just dooming
4010 // that cache entry so there is a fighting chance of getting things on the
4011 // right track.
4012
4013 nsAutoCString lastModifiedCached;
4014 nsAutoCString lastModified304;
4015
4016 rv =
4017 mCachedResponseHead->GetHeader(nsHttp::Last_Modified, lastModifiedCached);
4018 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4019 rv = mResponseHead->GetHeader(nsHttp::Last_Modified, lastModified304);
4020 }
4021
4022 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !lastModified304.Equals(lastModifiedCached)) {
4023 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4024 ("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)
4025 "[%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)
4026 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)
;
4027
4028 mCacheEntry->AsyncDoom(nullptr);
4029 Telemetry::Accumulate(Telemetry::CACHE_LM_INCONSISTENT, true);
4030 }
4031
4032 // merge any new headers with the cached response headers
4033 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
4034
4035 // update the cached response head
4036 nsAutoCString head;
4037 mCachedResponseHead->Flatten(head, true);
4038 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
4039 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4040
4041 if (StaticPrefs::network_http_network_error_logging_enabled() &&
4042 LoadUsedNetwork() && !mReportedNEL) {
4043 if (nsCOMPtr<nsINetworkErrorLogging> nel =
4044 components::NetworkErrorLogging::Service()) {
4045 nel->GenerateNELReport(this);
4046 }
4047 mReportedNEL = true;
4048 }
4049
4050 // make the cached response be the current response
4051 mResponseHead = std::move(mCachedResponseHead);
4052
4053 UpdateInhibitPersistentCachingFlag();
4054
4055 rv = UpdateExpirationTime();
4056 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4057
4058 rv = AddCacheEntryHeaders(mCacheEntry);
4059 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4060
4061 // notify observers interested in looking at a reponse that has been
4062 // merged with any cached headers
4063 gHttpHandler->OnExamineMergedResponse(this);
4064
4065 mCachedContentIsValid = true;
4066
4067 // Tell other consumers the entry is OK to use
4068 rv = mCacheEntry->SetValid();
4069 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4070
4071 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
4072 nsresult rv = self->ReadFromCache();
4073 return aContinueProcessResponseFunc(self, rv);
4074 });
4075}
4076
4077// Determines if a request is a byte range request for a subrange,
4078// i.e. is a byte range request, but not a 0- byte range request.
4079static bool IsSubRangeRequest(nsHttpRequestHead& aRequestHead) {
4080 nsAutoCString byteRange;
4081 if (NS_FAILED(aRequestHead.GetHeader(nsHttp::Range, byteRange))((bool)(__builtin_expect(!!(NS_FAILED_impl(aRequestHead.GetHeader
(nsHttp::Range, byteRange))), 0)))
) {
4082 return false;
4083 }
4084
4085 if (byteRange.EqualsLiteral("bytes=0-")) {
4086#ifndef ANDROID
4087 glean::network::byte_range_request.Get("cacheable"_ns).Add(1);
4088#endif
4089 return false;
4090 }
4091#ifndef ANDROID
4092 glean::network::byte_range_request.Get("not_cacheable"_ns).Add(1);
4093#endif
4094 return true;
4095}
4096
4097nsresult nsHttpChannel::OpenCacheEntry(bool isHttps) {
4098 // Drop this flag here
4099 StoreConcurrentCacheAccess(0);
4100
4101 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)
;
4102
4103 // make sure we're not abusing this function
4104 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4104); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheEntry"
") (" "cache entry already open" ")"); do { *((volatile int*
)__null) = 4104; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4105
4106 if (mRequestHead.IsPost()) {
4107 // If the post id is already set then this is an attempt to replay
4108 // a post transaction via the cache. Otherwise, we need a unique
4109 // post id for this transaction.
4110 if (mPostID == 0) mPostID = gHttpHandler->GenerateUniqueID();
4111 } else if (!mRequestHead.IsGet() && !mRequestHead.IsHead()) {
4112 // don't use the cache for other types of requests
4113 return NS_OK;
4114 }
4115
4116 return OpenCacheEntryInternal(isHttps);
4117}
4118
4119nsresult nsHttpChannel::OpenCacheEntryInternal(bool isHttps) {
4120 nsresult rv;
4121
4122 if (LoadResuming()) {
4123 // We don't support caching for requests initiated
4124 // via nsIResumableChannel.
4125 return NS_OK;
4126 }
4127
4128 // Don't cache byte range requests which are subranges, only cache 0-
4129 // byte range requests.
4130 if (IsSubRangeRequest(mRequestHead)) {
4131 return NS_OK;
4132 }
4133
4134 // Handle correctly WaitForCacheEntry
4135 AutoCacheWaitFlags waitFlags(this);
4136
4137 nsAutoCString cacheKey;
4138
4139 nsCOMPtr<nsICacheStorageService> cacheStorageService(
4140 components::CacheStorage::Service());
4141 if (!cacheStorageService) {
4142 return NS_ERROR_NOT_AVAILABLE;
4143 }
4144
4145 nsCOMPtr<nsICacheStorage> cacheStorage;
4146 mCacheEntryURI = mURI;
4147
4148 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
4149 if (!info) {
4150 return NS_ERROR_FAILURE;
4151 }
4152
4153 uint32_t cacheEntryOpenFlags;
4154 bool offline = gIOService->IsOffline();
4155
4156 RefPtr<mozilla::dom::BrowsingContext> bc;
4157 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
4158
4159 bool maybeRCWN = false;
4160
4161 nsAutoCString cacheControlRequestHeader;
4162 Unused << mRequestHead.GetHeader(nsHttp::Cache_Control,
4163 cacheControlRequestHeader);
4164 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
4165 if (cacheControlRequest.NoStore()) {
4166 return NS_OK;
4167 }
4168
4169 bool forceOffline = bc && bc->Top()->GetForceOffline();
4170 if (offline || (mLoadFlags & INHIBIT_CACHING) || forceOffline) {
4171 if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
&&
4172 !offline && !forceOffline) {
4173 return NS_OK;
4174 }
4175 cacheEntryOpenFlags = nsICacheStorage::OPEN_READONLY;
4176 StoreCacheEntryIsReadOnly(true);
4177 } else if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
4178 cacheEntryOpenFlags = nsICacheStorage::OPEN_TRUNCATE;
4179 } else {
4180 cacheEntryOpenFlags =
4181 nsICacheStorage::OPEN_NORMALLY | nsICacheStorage::CHECK_MULTITHREADED;
4182 }
4183
4184 // Remember the request is a custom conditional request so that we can
4185 // process any 304 response correctly.
4186 StoreCustomConditionalRequest(
4187 mRequestHead.HasHeader(nsHttp::If_Modified_Since) ||
4188 mRequestHead.HasHeader(nsHttp::If_None_Match) ||
4189 mRequestHead.HasHeader(nsHttp::If_Unmodified_Since) ||
4190 mRequestHead.HasHeader(nsHttp::If_Match) ||
4191 mRequestHead.HasHeader(nsHttp::If_Range));
4192
4193 if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
4194 rv = cacheStorageService->MemoryCacheStorage(
4195 info, // ? choose app cache as well...
4196 getter_AddRefs(cacheStorage));
4197 } else if (LoadPinCacheContent()) {
4198 rv = cacheStorageService->PinningCacheStorage(info,
4199 getter_AddRefs(cacheStorage));
4200 } else {
4201 // Try to race only if we use disk cache storage
4202 maybeRCWN = mRequestHead.IsSafeMethod();
4203 rv = cacheStorageService->DiskCacheStorage(info,
4204 getter_AddRefs(cacheStorage));
4205 }
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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4206); return rv; } } while (false)
;
4207
4208 if ((mClassOfService.Flags() & nsIClassOfService::Leader) ||
4209 (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)) {
4210 cacheEntryOpenFlags |= nsICacheStorage::OPEN_PRIORITY;
4211 }
4212
4213 // Only for backward compatibility with the old cache back end.
4214 // When removed, remove the flags and related code snippets.
4215 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
4216 cacheEntryOpenFlags |= nsICacheStorage::OPEN_BYPASS_IF_BUSY;
4217 }
4218
4219 if (mPostID) {
4220 mCacheIdExtension.Append(nsPrintfCString("%d", mPostID));
4221 }
4222 if (LoadIsTRRServiceChannel()) {
4223 mCacheIdExtension.Append("TRR");
4224 }
4225 if (mRequestHead.IsHead()) {
4226 mCacheIdExtension.Append("HEAD");
4227 }
4228 bool isThirdParty = false;
4229 if (StaticPrefs::network_fetch_cache_partition_cross_origin() &&
4230 (NS_FAILED(mLoadInfo->TriggeringPrincipal()->IsThirdPartyChannel(((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
4231 this, &isThirdParty))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
||
4232 isThirdParty) &&
4233 (mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_FETCH ||
4234 mLoadInfo->InternalContentPolicyType() ==
4235 nsIContentPolicy::TYPE_XMLHTTPREQUEST ||
4236 mLoadInfo->InternalContentPolicyType() ==
4237 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_ASYNC ||
4238 mLoadInfo->InternalContentPolicyType() ==
4239 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_SYNC)) {
4240 mCacheIdExtension.Append("FETCH");
4241 }
4242
4243 mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY;
4244 mCacheQueueSizeWhenOpen =
4245 CacheStorageService::CacheQueueSize(mCacheOpenWithPriority);
4246
4247 if ((mNetworkTriggerDelay || StaticPrefs::network_http_rcwn_enabled()) &&
4248 maybeRCWN) {
4249 bool hasAltData = false;
4250 uint32_t sizeInKb = 0;
4251 rv = cacheStorage->GetCacheIndexEntryAttrs(
4252 mCacheEntryURI, mCacheIdExtension, &hasAltData, &sizeInKb);
4253
4254 // We will attempt to race the network vs the cache if we've found
4255 // this entry in the cache index, and it has appropriate attributes
4256 // (doesn't have alt-data, and has a small size)
4257 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !hasAltData &&
4258 sizeInKb < StaticPrefs::network_http_rcwn_small_resource_size_kb()) {
4259 MaybeRaceCacheWithNetwork();
4260 }
4261 }
4262
4263 if (!mCacheOpenDelay) {
4264 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on the main thread" ")"); do { *((volatile
int*)__null) = 4264; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4265 if (mNetworkTriggered) {
4266 mRaceCacheWithNetwork = StaticPrefs::network_http_rcwn_enabled();
4267 }
4268 rv = cacheStorage->AsyncOpenURI(mCacheEntryURI, mCacheIdExtension,
4269 cacheEntryOpenFlags, this);
4270 } else {
4271 // We pass `this` explicitly as a parameter due to the raw pointer
4272 // to refcounted object in lambda analysis.
4273 mCacheOpenFunc = [cacheEntryOpenFlags,
4274 cacheStorage](nsHttpChannel* self) -> void {
4275 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on the main thread" ")"); do { *((volatile
int*)__null) = 4275; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4276 cacheStorage->AsyncOpenURI(self->mCacheEntryURI, self->mCacheIdExtension,
4277 cacheEntryOpenFlags, self);
4278 };
4279
4280 // calls nsHttpChannel::Notify after `mCacheOpenDelay` milliseconds
4281 auto callback = MakeRefPtr<TimerCallback>(this);
4282 NS_NewTimerWithCallback(getter_AddRefs(mCacheOpenTimer), callback,
4283 mCacheOpenDelay, nsITimer::TYPE_ONE_SHOT);
4284 }
4285 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4285); return rv; } } while (false)
;
4286
4287 waitFlags.Keep(WAIT_FOR_CACHE_ENTRY);
4288
4289 return NS_OK;
4290}
4291
4292nsresult nsHttpChannel::CheckPartial(nsICacheEntry* aEntry, int64_t* aSize,
4293 int64_t* aContentLength) {
4294 return nsHttp::CheckPartial(
4295 aEntry, aSize, aContentLength,
4296 mCachedResponseHead ? mCachedResponseHead.get() : mResponseHead.get());
4297}
4298
4299void nsHttpChannel::UntieValidationRequest() {
4300 DebugOnly<nsresult> rv{};
4301 // Make the request unconditional again.
4302 rv = mRequestHead.ClearHeader(nsHttp::If_Modified_Since);
4303 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4303; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4304 rv = mRequestHead.ClearHeader(nsHttp::If_None_Match);
4305 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4305; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4306 rv = mRequestHead.ClearHeader(nsHttp::ETag);
4307 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4307); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4307; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4308}
4309
4310NS_IMETHODIMPnsresult
4311nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, uint32_t* aResult) {
4312 nsresult rv = NS_OK;
4313
4314 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)
4315 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)
;
4316
4317 mozilla::MutexAutoLock lock(mRCWNLock);
4318
4319 if (mRaceCacheWithNetwork && mFirstResponseSource == RESPONSE_FROM_NETWORK) {
4320 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 because we've already got one from the "
"network\n"); } } while (0)
4321 ("Not using cached response because we've already got one from the "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 because we've already got one from the "
"network\n"); } } while (0)
4322 "network\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 because we've already got one from the "
"network\n"); } } while (0)
;
4323 *aResult = ENTRY_NOT_WANTED;
4324
4325 // Net-win indicates that mOnStartRequestTimestamp is from net.
4326 int64_t savedTime =
4327 (TimeStamp::Now() - mOnStartRequestTimestamp).ToMilliseconds();
4328 Telemetry::Accumulate(Telemetry::NETWORK_RACE_CACHE_WITH_NETWORK_SAVED_TIME,
4329 savedTime);
4330 return NS_OK;
4331 }
4332 if (mRaceCacheWithNetwork && mFirstResponseSource == RESPONSE_PENDING) {
4333 mOnCacheEntryCheckTimestamp = TimeStamp::Now();
4334 }
4335
4336 nsAutoCString cacheControlRequestHeader;
4337 Unused << mRequestHead.GetHeader(nsHttp::Cache_Control,
4338 cacheControlRequestHeader);
4339 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
4340
4341 if (cacheControlRequest.NoStore()) {
4342 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4343 ("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)
4344 "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)
;
4345 *aResult = ENTRY_NOT_WANTED;
4346 return NS_OK;
4347 }
4348
4349 // Be pessimistic: assume the cache entry has no useful data.
4350 *aResult = ENTRY_WANTED;
4351 mCachedContentIsValid = false;
4352
4353 nsCString buf;
4354
4355 // Get the method that was used to generate the cached response
4356 rv = entry->GetMetaDataElement("request-method", getter_Copies(buf));
4357 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4357); return rv; } } while (false)
;
4358
4359 bool methodWasHead = buf.EqualsLiteral("HEAD");
4360 bool methodWasGet = buf.EqualsLiteral("GET");
4361
4362 if (methodWasHead) {
4363 // The cached response does not contain an entity. We can only reuse
4364 // the response if the current request is also HEAD.
4365 if (!mRequestHead.IsHead()) {
4366 *aResult = ENTRY_NOT_WANTED;
4367 return NS_OK;
4368 }
4369 }
4370 buf.Adopt(nullptr);
4371
4372 // We'll need this value in later computations...
4373 uint32_t lastModifiedTime;
4374 rv = entry->GetLastModified(&lastModifiedTime);
4375 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4375); return rv; } } while (false)
;
4376
4377 // Determine if this is the first time that this cache entry
4378 // has been accessed during this session.
4379 bool fromPreviousSession =
4380 (gHttpHandler->SessionStartTime() > lastModifiedTime);
4381
4382 // Get the cached HTTP response headers
4383 mCachedResponseHead = MakeUnique<nsHttpResponseHead>();
4384
4385 rv = nsHttp::GetHttpResponseHeadFromCacheEntry(entry,
4386 mCachedResponseHead.get());
4387 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4387); return rv; } } while (false)
;
4388
4389 bool isCachedRedirect = WillRedirect(*mCachedResponseHead);
4390
4391 // Do not return 304 responses from the cache, and also do not return
4392 // any other non-redirect 3xx responses from the cache (see bug 759043).
4393 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4394); return NS_ERROR_ABORT; } } while (false)
4394 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4394); return NS_ERROR_ABORT; } } while (false)
;
4395
4396 if (mCachedResponseHead->NoStore() && LoadCacheEntryIsReadOnly()) {
4397 // This prevents loading no-store responses when navigating back
4398 // while the browser is set to work offline.
4399 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)
;
4400 mLoadFlags |= nsIRequest::INHIBIT_CACHING;
4401 }
4402
4403 // Don't bother to validate items that are read-only,
4404 // unless they are read-only because of INHIBIT_CACHING
4405 if ((LoadCacheEntryIsReadOnly() &&
4406 !(mLoadFlags & nsIRequest::INHIBIT_CACHING))) {
4407 int64_t size, contentLength;
4408 rv = CheckPartial(entry, &size, &contentLength);
4409 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4409); return rv; } } while (false)
;
4410
4411 if (contentLength != int64_t(-1) && contentLength != size) {
4412 *aResult = ENTRY_NOT_WANTED;
4413 return NS_OK;
4414 }
4415
4416 rv = OpenCacheInputStream(entry, true);
4417 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4418 mCachedContentIsValid = true;
4419 }
4420 return rv;
4421 }
4422
4423 bool wantCompleteEntry = false;
4424
4425 if (!methodWasHead && !isCachedRedirect) {
4426 // If the cached content-length is set and it does not match the data
4427 // size of the cached content, then the cached response is partial...
4428 // either we need to issue a byte range request or we need to refetch
4429 // the entire document.
4430 //
4431 // We exclude redirects from this check because we (usually) strip the
4432 // entity when we store the cache entry, and even if we didn't, we
4433 // always ignore a cached redirect's entity anyway. See bug 759043.
4434 int64_t size, contentLength;
4435 rv = CheckPartial(entry, &size, &contentLength);
4436 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4436); return rv; } } while (false)
;
4437
4438 if (size == int64_t(-1)) {
4439 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)
;
4440 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
4441 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4442 (" 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)
4443 "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)
;
4444
4445 *aResult = ENTRY_NOT_WANTED;
4446 return NS_OK;
4447 }
4448
4449 // Ignore !(size > 0) from the resumability condition
4450 if (!IsResumable(size, contentLength, true)) {
4451 if (IsNavigation()) {
4452 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4453 (" 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)
4454 "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)
;
4455 *aResult = ENTRY_NOT_WANTED;
4456 return NS_OK;
4457 }
4458
4459 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4460 (" 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)
4461 "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)
;
4462
4463 wantCompleteEntry = true;
4464 } else {
4465 StoreConcurrentCacheAccess(1);
4466 }
4467 } else if (contentLength != int64_t(-1) && contentLength != size) {
4468 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4469 ("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)
4470 "[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)
4471 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)
;
4472
4473 rv = MaybeSetupByteRangeRequest(size, contentLength);
4474 StoreCachedContentIsPartial(NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest());
4475 if (LoadCachedContentIsPartial()) {
4476 rv = OpenCacheInputStream(entry, false);
4477 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4478 UntieByteRangeRequest();
4479 return rv;
4480 }
4481
4482 *aResult = ENTRY_NEEDS_REVALIDATION;
4483 return NS_OK;
4484 }
4485
4486 if (size == 0 && LoadCacheOnlyMetadata()) {
4487 // Don't break cache entry load when the entry's data size
4488 // is 0 and CacheOnlyMetadata flag is set. In that case we
4489 // want to proceed since the LOAD_ONLY_IF_MODIFIED flag is
4490 // also set.
4491 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4491); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadFlags & LOAD_ONLY_IF_MODIFIED"
")"); do { *((volatile int*)__null) = 4491; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4492 } else {
4493 return rv;
4494 }
4495 }
4496 }
4497
4498 bool isHttps = mURI->SchemeIs("https");
4499
4500 bool doValidation = false;
4501 bool doBackgroundValidation = false;
4502 bool canAddImsHeader = true;
4503
4504 bool isForcedValid = false;
4505 entry->GetIsForcedValid(&isForcedValid);
4506 auto prefetchStatus = Telemetry::LABELS_PREDICTOR_PREFETCH_USE_STATUS::Used;
4507
4508 bool weaklyFramed, isImmutable;
4509 nsHttp::DetermineFramingAndImmutability(entry, mCachedResponseHead.get(),
4510 isHttps, &weaklyFramed, &isImmutable);
4511
4512 // Cached entry is not the entity we request (see bug #633743)
4513 if (ResponseWouldVary(entry)) {
4514 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)
;
4515 canAddImsHeader = false;
4516 doValidation = true;
4517 prefetchStatus = Telemetry::LABELS_PREDICTOR_PREFETCH_USE_STATUS::WouldVary;
4518 } else {
4519 if (mCachedResponseHead->ExpiresInPast() ||
4520 mCachedResponseHead->MustValidateIfExpired()) {
4521 prefetchStatus = Telemetry::LABELS_PREDICTOR_PREFETCH_USE_STATUS::Expired;
4522 }
4523 doValidation = nsHttp::ValidationRequired(
4524 isForcedValid, mCachedResponseHead.get(), mLoadFlags,
4525 LoadAllowStaleCacheContent(), LoadForceValidateCacheContent(),
4526 isImmutable, LoadCustomConditionalRequest(), mRequestHead, entry,
4527 cacheControlRequest, fromPreviousSession, &doBackgroundValidation);
4528 }
4529
4530 nsAutoCString requestedETag;
4531 if (!doValidation &&
4532 NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::If_Match, requestedETag))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::If_Match, requestedETag))), 1)))
&&
4533 (methodWasGet || methodWasHead)) {
4534 nsAutoCString cachedETag;
4535 Unused << mCachedResponseHead->GetHeader(nsHttp::ETag, cachedETag);
4536 if (!cachedETag.IsEmpty() && (StringBeginsWith(cachedETag, "W/"_ns) ||
4537 !requestedETag.Equals(cachedETag))) {
4538 // User has defined If-Match header, if the cached entry is not
4539 // matching the provided header value or the cached ETag is weak,
4540 // force validation.
4541 doValidation = true;
4542 }
4543 }
4544
4545 // Previous error should not be propagated.
4546 rv = NS_OK;
4547
4548 if (!doValidation) {
4549 //
4550 // Check the authorization headers used to generate the cache entry.
4551 // We must validate the cache entry if:
4552 //
4553 // 1) the cache entry was generated prior to this session w/
4554 // credentials (see bug 103402).
4555 // 2) the cache entry was generated w/o credentials, but would now
4556 // require credentials (see bug 96705).
4557 //
4558 // NOTE: this does not apply to proxy authentication.
4559 //
4560 entry->GetMetaDataElement("auth", getter_Copies(buf));
4561 doValidation =
4562 (fromPreviousSession && !buf.IsEmpty()) ||
4563 (buf.IsEmpty() && mRequestHead.HasHeader(nsHttp::Authorization));
4564 if (doValidation) {
4565 prefetchStatus = Telemetry::LABELS_PREDICTOR_PREFETCH_USE_STATUS::Auth;
4566 }
4567 }
4568
4569 // Bug #561276: We maintain a chain of cache-keys which returns cached
4570 // 3xx-responses (redirects) in order to detect cycles. If a cycle is
4571 // found, ignore the cached response and hit the net. Otherwise, use
4572 // the cached response and add the cache-key to the chain. Note that
4573 // a limited number of redirects (cached or not) is allowed and is
4574 // enforced independently of this mechanism
4575 if (!doValidation && isCachedRedirect) {
4576 nsAutoCString cacheKey;
4577 rv = GenerateCacheKey(mPostID, cacheKey);
4578 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4578; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4579
4580 auto redirectedCachekeys = mRedirectedCachekeys.Lock();
4581 auto& ref = redirectedCachekeys.ref();
4582 if (!ref) {
4583 ref = MakeUnique<nsTArray<nsCString>>();
4584 } else if (ref->Contains(cacheKey)) {
4585 doValidation = true;
4586 }
4587
4588 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)
4589 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)
;
4590
4591 // Append cacheKey if not in the chain already
4592 if (!doValidation) {
4593 ref->AppendElement(cacheKey);
4594 } else {
4595 prefetchStatus =
4596 Telemetry::LABELS_PREDICTOR_PREFETCH_USE_STATUS::Redirect;
4597 }
4598 }
4599
4600 mCachedContentIsValid = !doValidation;
4601
4602 if (isForcedValid) {
4603 // Telemetry value is only useful if this was a prefetched item
4604 if (!doValidation) {
4605 // Could have gotten to a funky state with some of the if chain above
4606 // and in nsHttp::ValidationRequired. Make sure we get it right here.
4607 prefetchStatus = Telemetry::LABELS_PREDICTOR_PREFETCH_USE_STATUS::Used;
4608
4609 entry->MarkForcedValidUse();
4610 }
4611 Telemetry::AccumulateCategorical(prefetchStatus);
4612 }
4613
4614 if (doValidation) {
4615 //
4616 // now, we are definitely going to issue a HTTP request to the server.
4617 // make it conditional if possible.
4618 //
4619 // do not attempt to validate no-store content, since servers will not
4620 // expect it to be cached. (we only keep it in our cache for the
4621 // purposes of back/forward, etc.)
4622 //
4623 // the request method MUST be either GET or HEAD (see bug 175641) and
4624 // the cached response code must be < 400
4625 //
4626 // the cached content must not be weakly framed
4627 //
4628 // do not override conditional headers when consumer has defined its own
4629 if (!mCachedResponseHead->NoStore() &&
4630 (mRequestHead.IsGet() || mRequestHead.IsHead()) &&
4631 !LoadCustomConditionalRequest() && !weaklyFramed &&
4632 (mCachedResponseHead->Status() < 400)) {
4633 if (LoadConcurrentCacheAccess()) {
4634 // In case of concurrent read and also validation request we
4635 // must wait for the current writer to close the output stream
4636 // first. Otherwise, when the writer's job would have been interrupted
4637 // before all the data were downloaded, we'd have to do a range request
4638 // which would be a second request in line during this channel's
4639 // life-time. nsHttpChannel is not designed to do that, so rather
4640 // turn off concurrent read and wait for entry's completion.
4641 // Then only re-validation or range-re-validation request will go out.
4642 StoreConcurrentCacheAccess(0);
4643 // This will cause that OnCacheEntryCheck is called again with the same
4644 // entry after the writer is done.
4645 wantCompleteEntry = true;
4646 } else {
4647 nsAutoCString val;
4648 // Add If-Modified-Since header if a Last-Modified was given
4649 // and we are allowed to do this (see bugs 510359 and 269303)
4650 if (canAddImsHeader) {
4651 Unused << mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
4652 if (!val.IsEmpty()) {
4653 rv = mRequestHead.SetHeader(nsHttp::If_Modified_Since, val);
4654 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4654; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4655 }
4656 }
4657 // Add If-None-Match header if an ETag was given in the response
4658 Unused << mCachedResponseHead->GetHeader(nsHttp::ETag, val);
4659 if (!val.IsEmpty()) {
4660 rv = mRequestHead.SetHeader(nsHttp::If_None_Match, val);
4661 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4661); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4661; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4662 }
4663 mDidReval = true;
4664 }
4665 }
4666 }
4667
4668 if (mCachedContentIsValid || mDidReval) {
4669 rv = OpenCacheInputStream(entry, mCachedContentIsValid);
4670 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4671 // If we can't get the entity then we have to act as though we
4672 // don't have the cache entry.
4673 if (mDidReval) {
4674 UntieValidationRequest();
4675 mDidReval = false;
4676 }
4677 mCachedContentIsValid = false;
4678 }
4679 }
4680
4681 if (mDidReval) {
4682 *aResult = ENTRY_NEEDS_REVALIDATION;
4683 } else if (wantCompleteEntry) {
4684 *aResult = RECHECK_AFTER_WRITE_FINISHED;
4685 } else {
4686 *aResult = ENTRY_WANTED;
4687
4688 if (doBackgroundValidation) {
4689 PerformBackgroundCacheRevalidation();
4690 }
4691 }
4692
4693 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHTTPChannel::OnCacheEntryCheck exit [this=%p doValidation=%d "
"result=%d]\n", this, doValidation, *aResult); } } while (0)
4694 ("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)
4695 "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)
4696 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)
;
4697 return rv;
4698}
4699
4700NS_IMETHODIMPnsresult
4701nsHttpChannel::OnCacheEntryAvailable(nsICacheEntry* entry, bool aNew,
4702 nsresult status) {
4703 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4703); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 4703; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4704
4705 nsresult rv;
4706
4707 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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" "]\n", this, entry, aNew, static_cast<uint32_t>(status
)); } } while (0)
4708 ("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" "]\n", this, entry, aNew, static_cast<uint32_t>(status
)); } } while (0)
4709 "new=%d 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::OnCacheEntryAvailable [this=%p entry=%p " "new=%d status=%"
"x" "]\n", this, entry, aNew, static_cast<uint32_t>(status
)); } } while (0)
4710 this, entry, aNew, 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::OnCacheEntryAvailable [this=%p entry=%p " "new=%d status=%"
"x" "]\n", this, entry, aNew, static_cast<uint32_t>(status
)); } } while (0)
;
4711
4712 // if the channel's already fired onStopRequest, then we should ignore
4713 // this event.
4714 if (!LoadIsPending()) {
4715 mCacheInputStream.CloseAndRelease();
4716 return NS_OK;
4717 }
4718
4719 rv = OnCacheEntryAvailableInternal(entry, aNew, status);
4720 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4721 CloseCacheEntry(false);
4722 if (mRaceCacheWithNetwork && mNetworkTriggered &&
4723 mFirstResponseSource != RESPONSE_FROM_CACHE) {
4724 // Ignore the error if we're racing cache with network and the cache
4725 // didn't win, The network part will handle cancelation or any other
4726 // error. Otherwise we could end up calling the listener twice, see
4727 // bug 1397593.
4728 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 calling AsyncAbort() because we're racing cache with "
"network"); } } while (0)
4729 (" not calling AsyncAbort() because we're racing cache with "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 calling AsyncAbort() because we're racing cache with "
"network"); } } while (0)
4730 "network"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 calling AsyncAbort() because we're racing cache with "
"network"); } } while (0)
;
4731 } else {
4732 Unused << AsyncAbort(rv);
4733 }
4734 }
4735
4736 return NS_OK;
4737}
4738
4739nsresult nsHttpChannel::OnCacheEntryAvailableInternal(nsICacheEntry* entry,
4740 bool aNew,
4741 nsresult status) {
4742 nsresult rv;
4743
4744 if (mCanceled) {
4745 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)
4746 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)
;
4747 return mStatus;
4748 }
4749
4750 if (mIgnoreCacheEntry) {
4751 if (!entry || aNew) {
4752 // We use this flag later to decide whether to report
4753 // LABELS_NETWORK_RACE_CACHE_VALIDATION::NotSent. We didn't have
4754 // an usable entry, so drop the flag.
4755 mIgnoreCacheEntry = false;
4756 }
4757 entry = nullptr;
4758 status = NS_ERROR_NOT_AVAILABLE;
4759 }
4760
4761 rv = OnNormalCacheEntryAvailable(entry, aNew, status);
4762
4763 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
4764 return NS_ERROR_DOCUMENT_NOT_CACHED;
4765 }
4766
4767 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4768 return rv;
4769 }
4770
4771 // We may be waiting for more callbacks...
4772 if (AwaitingCacheCallbacks()) {
4773 return NS_OK;
4774 }
4775
4776 if (mRaceCacheWithNetwork && ((mCacheEntry && !mCachedContentIsValid &&
4777 (mDidReval || LoadCachedContentIsPartial())) ||
4778 mIgnoreCacheEntry)) {
4779 // We won't send the conditional request because the unconditional
4780 // request was already sent (see bug 1377223).
4781 AccumulateCategorical(
4782 Telemetry::LABELS_NETWORK_RACE_CACHE_VALIDATION::NotSent);
4783 }
4784
4785 if (mRaceCacheWithNetwork && mCachedContentIsValid) {
4786 Unused << ReadFromCache();
4787 }
4788
4789 return TriggerNetwork();
4790}
4791
4792nsresult nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntry* aEntry,
4793 bool aNew,
4794 nsresult aEntryStatus) {
4795 StoreWaitForCacheEntry(LoadWaitForCacheEntry() & ~WAIT_FOR_CACHE_ENTRY);
4796
4797 if (NS_FAILED(aEntryStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aEntryStatus)), 0)
))
|| aNew) {
4798 // Make sure this flag is dropped. It may happen the entry is doomed
4799 // between OnCacheEntryCheck and OnCacheEntryAvailable.
4800 mCachedContentIsValid = false;
4801
4802 // From the same reason remove any conditional headers added
4803 // in OnCacheEntryCheck.
4804 if (mDidReval) {
4805 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)
;
4806 UntieValidationRequest();
4807 mDidReval = false;
4808 }
4809
4810 if (LoadCachedContentIsPartial()) {
4811 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)
;
4812 UntieByteRangeRequest();
4813 StoreCachedContentIsPartial(false);
4814 }
4815
4816 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
4817 // if this channel is only allowed to pull from the cache, then
4818 // we must fail if we were unable to open a cache entry for read.
4819 return NS_ERROR_DOCUMENT_NOT_CACHED;
4820 }
4821 }
4822
4823 if (NS_SUCCEEDED(aEntryStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aEntryStatus)), 1
)))
) {
4824 mCacheEntry = aEntry;
4825 StoreCacheEntryIsWriteOnly(aNew);
4826
4827 if (!aNew && !mAsyncOpenTime.IsNull()) {
4828 // We use microseconds for IO operations. For consistency let's use
4829 // microseconds here too.
4830 uint32_t duration = (TimeStamp::Now() - mAsyncOpenTime).ToMicroseconds();
4831 bool isSlow = false;
4832 if ((mCacheOpenWithPriority &&
4833 mCacheQueueSizeWhenOpen >=
4834 StaticPrefs::
4835 network_http_rcwn_cache_queue_priority_threshold()) ||
4836 (!mCacheOpenWithPriority &&
4837 mCacheQueueSizeWhenOpen >=
4838 StaticPrefs::network_http_rcwn_cache_queue_normal_threshold())) {
4839 isSlow = true;
4840 }
4841 CacheFileUtils::CachePerfStats::AddValue(
4842 CacheFileUtils::CachePerfStats::ENTRY_OPEN, duration, isSlow);
4843 }
4844 }
4845
4846 return NS_OK;
4847}
4848
4849// Generates the proper cache-key for this instance of nsHttpChannel
4850nsresult nsHttpChannel::GenerateCacheKey(uint32_t postID,
4851 nsACString& cacheKey) {
4852 AssembleCacheKey(mSpec.get(), postID, cacheKey);
4853 return NS_OK;
4854}
4855
4856// Assembles a cache-key from the given pieces of information and |mLoadFlags|
4857void nsHttpChannel::AssembleCacheKey(const char* spec, uint32_t postID,
4858 nsACString& cacheKey) {
4859 cacheKey.Truncate();
4860
4861 if (mLoadFlags & LOAD_ANONYMOUS) {
4862 cacheKey.AssignLiteral("anon&");
4863 }
4864
4865 if (postID) {
4866 char buf[32];
4867 SprintfLiteral(buf, "id=%x&", postID);
4868 cacheKey.Append(buf);
4869 }
4870
4871 if (!cacheKey.IsEmpty()) {
4872 cacheKey.AppendLiteral("uri=");
4873 }
4874
4875 // Strip any trailing #ref from the URL before using it as the key
4876 const char* p = strchr(spec, '#');
4877 if (p) {
4878 cacheKey.Append(spec, p - spec);
4879 } else {
4880 cacheKey.Append(spec);
4881 }
4882}
4883
4884nsresult DoUpdateExpirationTime(nsHttpChannel* aSelf,
4885 nsICacheEntry* aCacheEntry,
4886 nsHttpResponseHead* aResponseHead,
4887 uint32_t& aExpirationTime) {
4888 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aExpirationTime == 0"
")"); do { *((volatile int*)__null) = 4888; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4889 NS_ENSURE_TRUE(aResponseHead, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aResponseHead)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResponseHead" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4889); return NS_ERROR_FAILURE; } } while (false)
;
4890
4891 nsresult rv;
4892
4893 if (!aResponseHead->MustValidate()) {
4894 // For stale-while-revalidate we use expiration time as the absolute base
4895 // for calculation of the stale window absolute end time. Hence, when the
4896 // entry may be served w/o revalidation, we need a non-zero value for the
4897 // expiration time. Let's set it to |now|, which basicly means "expired",
4898 // same as when set to 0.
4899 uint32_t now = NowInSeconds()PRTimeToSeconds(PR_Now());
4900 aExpirationTime = now;
4901
4902 uint32_t freshnessLifetime = 0;
4903
4904 rv = aResponseHead->ComputeFreshnessLifetime(&freshnessLifetime);
4905 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4906
4907 if (freshnessLifetime > 0) {
4908 uint32_t currentAge = 0;
4909
4910 rv = aResponseHead->ComputeCurrentAge(now, aSelf->GetRequestTime(),
4911 &currentAge);
4912 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4913
4914 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)
4915 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)
;
4916
4917 if (freshnessLifetime > currentAge) {
4918 uint32_t timeRemaining = freshnessLifetime - currentAge;
4919 // be careful... now + timeRemaining may overflow
4920 if (now + timeRemaining < now) {
4921 aExpirationTime = uint32_t(-1);
4922 } else {
4923 aExpirationTime = now + timeRemaining;
4924 }
4925 }
4926 }
4927 }
4928
4929 rv = aCacheEntry->SetExpirationTime(aExpirationTime);
4930 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4930); return rv; } } while (false)
;
4931
4932 return rv;
4933}
4934
4935// UpdateExpirationTime is called when a new response comes in from the server.
4936// It updates the stored response-time and sets the expiration time on the
4937// cache entry.
4938//
4939// From section 13.2.4 of RFC2616, we compute expiration time as follows:
4940//
4941// timeRemaining = freshnessLifetime - currentAge
4942// expirationTime = now + timeRemaining
4943//
4944nsresult nsHttpChannel::UpdateExpirationTime() {
4945 uint32_t expirationTime = 0;
4946 nsresult rv = DoUpdateExpirationTime(this, mCacheEntry, mResponseHead.get(),
4947 expirationTime);
4948 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4948); return rv; } } while (false)
;
4949
4950 return NS_OK;
4951}
4952
4953nsresult nsHttpChannel::OpenCacheInputStream(nsICacheEntry* cacheEntry,
4954 bool startBuffering) {
4955 nsresult rv;
4956
4957 if (mURI->SchemeIs("https")) {
4958 rv = cacheEntry->GetSecurityInfo(getter_AddRefs(mCachedSecurityInfo));
4959 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4960 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)
4961 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)
;
4962 NS_WARNING("failed to parse security-info")NS_DebugBreak(NS_DEBUG_WARNING, "failed to parse security-info"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4962)
;
4963 cacheEntry->AsyncDoom(nullptr);
4964 return rv;
4965 }
4966
4967 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 4967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedSecurityInfo"
")"); do { *((volatile int*)__null) = 4967; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4968 if (!mCachedSecurityInfo) {
4969 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4970 ("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)
4971 "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)
4972 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)
;
4973 cacheEntry->AsyncDoom(nullptr);
4974 return NS_ERROR_UNEXPECTED; // XXX error code
4975 }
4976 }
4977
4978 // Keep the conditions below in sync with the conditions in ReadFromCache.
4979
4980 rv = NS_OK;
Value stored to 'rv' is never read
4981
4982 if (WillRedirect(*mCachedResponseHead)) {
4983 // Do not even try to read the entity for a redirect because we do not
4984 // return an entity to the application when we process redirects.
4985 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
)
;
4986 return NS_OK;
4987 }
4988
4989 if ((mLoadFlags & nsICachingChannel::LOAD_ONLY_IF_MODIFIED) &&
4990 !LoadCachedContentIsPartial()) {
4991 // For LOAD_ONLY_IF_MODIFIED, we usually don't have to deal with the
4992 // cached entity.
4993 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4994 ("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)
4995 "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)
;
4996 return NS_OK;
4997 }
4998
4999 // Open an input stream for the entity, so that the call to OpenInputStream
5000 // happens off the main thread.
5001 nsCOMPtr<nsIInputStream> stream;
5002
5003 // If an alternate representation was requested, try to open the alt
5004 // input stream.
5005 // If the entry has a "is-from-child" metadata, then only open the altdata
5006 // stream if the consumer is also from child.
5007 bool altDataFromChild = false;
5008 {
5009 nsCString value;
5010 rv = cacheEntry->GetMetaDataElement("alt-data-from-child",
5011 getter_Copies(value));
5012 altDataFromChild = !value.IsEmpty();
5013 }
5014
5015 nsAutoCString altDataType;
5016 Unused << cacheEntry->GetAltDataType(altDataType);
5017
5018 nsAutoCString contentType;
5019 mCachedResponseHead->ContentType(contentType);
5020
5021 bool foundAltData = false;
5022 bool deliverAltData = true;
5023 if (!LoadDisableAltDataCache() && !altDataType.IsEmpty() &&
5024 !mPreferredCachedAltDataTypes.IsEmpty() &&
5025 altDataFromChild == LoadAltDataForChild()) {
5026 for (auto& pref : mPreferredCachedAltDataTypes) {
5027 if (pref.type() == altDataType &&
5028 (pref.contentType().IsEmpty() || pref.contentType() == contentType)) {
5029 foundAltData = true;
5030 deliverAltData =
5031 pref.deliverAltData() ==
5032 nsICacheInfoChannel::PreferredAlternativeDataDeliveryType::ASYNC;
5033 break;
5034 }
5035 }
5036 }
5037
5038 nsCOMPtr<nsIInputStream> altData;
5039 int64_t altDataSize = -1;
5040 if (foundAltData) {
5041 rv = cacheEntry->OpenAlternativeInputStream(altDataType,
5042 getter_AddRefs(altData));
5043 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5044 // We have succeeded.
5045 mAvailableCachedAltDataType = altDataType;
5046 StoreDeliveringAltData(deliverAltData);
5047
5048 // Set the correct data size on the channel.
5049 Unused << cacheEntry->GetAltDataSize(&altDataSize);
5050 mAltDataLength = altDataSize;
5051
5052 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)
5053 ", 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)
5054 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)
;
5055
5056 if (deliverAltData) {
5057 stream = altData;
5058 }
5059 }
5060 }
5061
5062 if (!stream) {
5063 rv = cacheEntry->OpenInputStream(0, getter_AddRefs(stream));
5064 }
5065
5066 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5067 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
5068 ("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)
5069 "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)
5070 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)
;
5071 return rv;
5072 }
5073
5074 if (startBuffering) {
5075 bool nonBlocking;
5076 rv = stream->IsNonBlocking(&nonBlocking);
5077 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && nonBlocking) startBuffering = false;
5078 }
5079
5080 if (!startBuffering) {
5081 // Bypass wrapping the input stream for the new cache back-end since
5082 // nsIStreamTransportService expects a blocking stream. Preloading of
5083 // the data must be done on the level of the cache backend, internally.
5084 //
5085 // We do not connect the stream to the stream transport service if we
5086 // have to validate the entry with the server. If we did, we would get
5087 // into a race condition between the stream transport service reading
5088 // the existing contents and the opening of the cache entry's output
5089 // stream to write the new contents in the case where we get a non-304
5090 // response.
5091 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
5092 ("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)
5093 "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)
5094 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)
;
5095 mCacheInputStream.takeOver(stream);
5096 return rv;
5097 }
5098
5099 // Have the stream transport service start reading the entity on one of its
5100 // background threads.
5101
5102 nsCOMPtr<nsITransport> transport;
5103 nsCOMPtr<nsIInputStream> wrapper;
5104
5105 nsCOMPtr<nsIStreamTransportService> sts(
5106 components::StreamTransport::Service());
5107 rv = sts ? NS_OK : NS_ERROR_NOT_AVAILABLE;
5108 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5109 rv = sts->CreateInputTransport(stream, true, getter_AddRefs(transport));
5110 }
5111 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5112 rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(wrapper));
5113 }
5114 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5115 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
5116 ("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)
5117 "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)
5118 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)
;
5119 } else {
5120 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Failed to open cache input stream [channel=%p, " "wrapper=%p, transport=%p, stream=%p]"
, this, wrapper.get(), transport.get(), stream.get()); } } while
(0)
5121 ("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)
5122 "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)
5123 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)
;
5124
5125 stream->Close();
5126 return rv;
5127 }
5128
5129 mCacheInputStream.takeOver(wrapper);
5130
5131 return NS_OK;
5132}
5133
5134// Actually process the cached response that we started to handle in CheckCache
5135// and/or StartBufferingCachedEntity.
5136nsresult nsHttpChannel::ReadFromCache(void) {
5137 NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mCacheEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mCacheEntry" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5137); return NS_ERROR_FAILURE; } } while (false)
;
5138 NS_ENSURE_TRUE(mCachedContentIsValid, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mCachedContentIsValid)), 0)))
{ NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mCachedContentIsValid"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5138); return NS_ERROR_FAILURE; } } while (false)
;
5139 NS_ENSURE_TRUE(!mCachePump, NS_OK)do { if ((__builtin_expect(!!(!(!mCachePump)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!mCachePump" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5139); return NS_OK; } } while (false)
; // already opened
5140
5141 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
5142 ("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)
5143 "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)
5144 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)
;
5145
5146 // When racing the cache with the network with a timer, and we get data from
5147 // the cache, we should prevent the timer from triggering a network request.
5148 if (mNetworkTriggerTimer) {
5149 mNetworkTriggerTimer->Cancel();
5150 mNetworkTriggerTimer = nullptr;
5151 }
5152
5153 if (mRaceCacheWithNetwork) {
5154 MOZ_ASSERT(mFirstResponseSource != RESPONSE_FROM_CACHE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFirstResponseSource != RESPONSE_FROM_CACHE)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mFirstResponseSource != RESPONSE_FROM_CACHE))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mFirstResponseSource != RESPONSE_FROM_CACHE"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5154); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFirstResponseSource != RESPONSE_FROM_CACHE"
")"); do { *((volatile int*)__null) = 5154; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5155 if (mFirstResponseSource == RESPONSE_PENDING) {
5156 LOG(("First response from cache\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "First response from cache\n"); } } while (0)
;
5157 mFirstResponseSource = RESPONSE_FROM_CACHE;
5158
5159 // Cancel the transaction because we will serve the request from the cache
5160 CancelNetworkRequest(NS_BINDING_ABORTED);
5161 if (mTransactionPump && mSuspendCount) {
5162 uint32_t suspendCount = mSuspendCount;
5163 while (suspendCount--) {
5164 mTransactionPump->Resume();
5165 }
5166 }
5167 mTransaction = nullptr;
5168 mTransactionPump = nullptr;
5169 } else {
5170 MOZ_ASSERT(mFirstResponseSource == RESPONSE_FROM_NETWORK)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFirstResponseSource == RESPONSE_FROM_NETWORK)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mFirstResponseSource == RESPONSE_FROM_NETWORK))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("mFirstResponseSource == RESPONSE_FROM_NETWORK"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFirstResponseSource == RESPONSE_FROM_NETWORK"
")"); do { *((volatile int*)__null) = 5170; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5171 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 because first response was from "
"network\n"); } } while (0)
5172 ("Skipping read from cache because first response was from "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Skipping read from cache because first response was from "
"network\n"); } } while (0)
5173 "network\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 because first response was from "
"network\n"); } } while (0)
;
5174
5175 if (!mOnCacheEntryCheckTimestamp.IsNull()) {
5176 TimeStamp currentTime = TimeStamp::Now();
5177 int64_t savedTime =
5178 (currentTime - mOnStartRequestTimestamp).ToMilliseconds();
5179 Telemetry::Accumulate(
5180 Telemetry::NETWORK_RACE_CACHE_WITH_NETWORK_SAVED_TIME, savedTime);
5181
5182 int64_t diffTime =
5183 (currentTime - mOnCacheEntryCheckTimestamp).ToMilliseconds();
5184 Telemetry::Accumulate(
5185 Telemetry::NETWORK_RACE_CACHE_WITH_NETWORK_OCEC_ON_START_DIFF,
5186 diffTime);
5187 }
5188 return NS_OK;
5189 }
5190 }
5191
5192 if (mCachedResponseHead) mResponseHead = std::move(mCachedResponseHead);
5193
5194 UpdateInhibitPersistentCachingFlag();
5195
5196 // if we don't already have security info, try to get it from the cache
5197 // entry. there are two cases to consider here: 1) we are just reading
5198 // from the cache, or 2) this may be due to a 304 not modified response,
5199 // in which case we could have security info from a socket transport.
5200 if (!mSecurityInfo) mSecurityInfo = mCachedSecurityInfo;
5201
5202 nsresult rv;
5203
5204 // Keep the conditions below in sync with the conditions in
5205 // StartBufferingCachedEntity.
5206
5207 if (WillRedirect(*mResponseHead)) {
5208 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
5209 // to avoid event dispatching latency.
5210 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { *((volatile int*)__null) = 5210; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5211 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)
;
5212 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
5213 }
5214
5215 if ((mLoadFlags & LOAD_ONLY_IF_MODIFIED) && !LoadCachedContentIsPartial()) {
5216 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
5217 ("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)
5218 "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)
;
5219 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { *((volatile int*)__null) = 5219; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5220 // TODO: Bug 759040 - We should call HandleAsyncNotModified directly
5221 // here, to avoid event dispatching latency.
5222 return AsyncCall(&nsHttpChannel::HandleAsyncNotModified);
5223 }
5224
5225 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5225); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheInputStream"
")"); do { *((volatile int*)__null) = 5225; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5226 if (!mCacheInputStream) {
5227 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "mCacheInputStream is null but we're expecting to "
"be able to read from it.", "Error", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5229); MOZ_PretendNoReturn(); } while (0)
5228 "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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5229); MOZ_PretendNoReturn(); } while (0)
5229 "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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5229); MOZ_PretendNoReturn(); } while (0)
;
5230 return NS_ERROR_UNEXPECTED;
5231 }
5232
5233 nsCOMPtr<nsIInputStream> inputStream = mCacheInputStream.forget();
5234
5235 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), inputStream, 0, 0,
5236 true);
5237 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5238 inputStream->Close();
5239 return rv;
5240 }
5241
5242 rv = mCachePump->AsyncRead(this);
5243 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5244
5245 if (LoadTimingEnabled()) mCacheReadStart = TimeStamp::Now();
5246
5247 uint32_t suspendCount = mSuspendCount;
5248 if (LoadAsyncResumePending()) {
5249 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
5250 (" 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)
5251 ", 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)
5252 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)
;
5253 ++suspendCount;
5254 }
5255 while (suspendCount--) {
5256 mCachePump->Suspend();
5257 }
5258
5259 return NS_OK;
5260}
5261
5262void nsHttpChannel::CloseCacheEntry(bool doomOnFailure) {
5263 mCacheInputStream.CloseAndRelease();
5264
5265 if (!mCacheEntry) return;
5266
5267 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)
5268 " 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)
5269 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)
5270 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)
;
5271
5272 // If we have begun to create or replace a cache entry, and that cache
5273 // entry is not complete and not resumable, then it needs to be doomed.
5274 // Otherwise, CheckCache will make the mistake of thinking that the
5275 // partial cache entry is complete.
5276
5277 bool doom = false;
5278 if (LoadInitedCacheEntry()) {
5279 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "oops" ")"); do { *((volatile int*)__null) = 5279; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
5280 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) && doomOnFailure && LoadCacheEntryIsWriteOnly() &&
5281 !mResponseHead->IsResumable()) {
5282 doom = true;
5283 }
5284 } else if (LoadCacheEntryIsWriteOnly()) {
5285 doom = true;
5286 }
5287
5288 if (doom) {
5289 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)
;
5290 mCacheEntry->AsyncDoom(nullptr);
5291 } else {
5292 // Store updated security info, makes cached EV status race less likely
5293 // (see bug 1040086)
5294 if (mSecurityInfo) {
5295 mCacheEntry->SetSecurityInfo(mSecurityInfo);
5296 }
5297 }
5298
5299 mCachedResponseHead = nullptr;
5300
5301 mCachePump = nullptr;
5302 // This releases the entry for other consumers to use.
5303 // We call Dismiss() in case someone still keeps a reference
5304 // to this entry handle.
5305 mCacheEntry->Dismiss();
5306 mCacheEntry = nullptr;
5307 StoreCacheEntryIsWriteOnly(false);
5308 StoreInitedCacheEntry(false);
5309}
5310
5311void nsHttpChannel::MaybeCreateCacheEntryWhenRCWN() {
5312 mozilla::MutexAutoLock lock(mRCWNLock);
5313
5314 // Create cache entry for writing only when we're racing cache with network
5315 // and we don't have the entry because network won.
5316 if (mCacheEntry || !mRaceCacheWithNetwork ||
5317 mFirstResponseSource != RESPONSE_FROM_NETWORK ||
5318 LoadCacheEntryIsReadOnly()) {
5319 return;
5320 }
5321
5322 LOG(("nsHttpChannel::MaybeCreateCacheEntryWhenRCWN [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::MaybeCreateCacheEntryWhenRCWN [this=%p]", this
); } } while (0)
;
5323
5324 nsCOMPtr<nsICacheStorageService> cacheStorageService(
5325 components::CacheStorage::Service());
5326 if (!cacheStorageService) {
5327 return;
5328 }
5329
5330 nsCOMPtr<nsICacheStorage> cacheStorage;
5331 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
5332 Unused << cacheStorageService->DiskCacheStorage(info,
5333 getter_AddRefs(cacheStorage));
5334 if (!cacheStorage) {
5335 return;
5336 }
5337
5338 Unused << cacheStorage->OpenTruncate(mCacheEntryURI, mCacheIdExtension,
5339 getter_AddRefs(mCacheEntry));
5340
5341 LOG((" created entry %p", 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
, " created entry %p", mCacheEntry.get()); } } while (0)
;
5342
5343 if (AwaitingCacheCallbacks()) {
5344 // Setting mIgnoreCacheEntry to true ensures that we won't close this
5345 // write-only entry in OnCacheEntryAvailable() if this method was called
5346 // after OnCacheEntryCheck().
5347 mIgnoreCacheEntry = true;
5348 }
5349
5350 mAvailableCachedAltDataType.Truncate();
5351 StoreDeliveringAltData(false);
5352 mAltDataLength = -1;
5353 mCacheInputStream.CloseAndRelease();
5354 mCachedContentIsValid = false;
5355}
5356
5357// Initialize the cache entry for writing.
5358// - finalize storage policy
5359// - store security info
5360// - update expiration time
5361// - store headers and other meta data
5362nsresult nsHttpChannel::InitCacheEntry() {
5363 nsresult rv;
5364
5365 NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mCacheEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mCacheEntry" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5365); return NS_ERROR_UNEXPECTED; } } while (false)
;
5366 // if only reading, nothing to be done here.
5367 if (LoadCacheEntryIsReadOnly()) return NS_OK;
5368
5369 // Don't cache the response again if already cached...
5370 if (mCachedContentIsValid) return NS_OK;
5371
5372 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)
5373 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)
;
5374
5375 bool recreate = !LoadCacheEntryIsWriteOnly();
5376 bool dontPersist = mLoadFlags & INHIBIT_PERSISTENT_CACHING;
5377
5378 if (!recreate && dontPersist) {
5379 // If the current entry is persistent but we inhibit peristence
5380 // then force recreation of the entry as memory/only.
5381 rv = mCacheEntry->GetPersistent(&recreate);
5382 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5383 }
5384
5385 if (recreate) {
5386 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
5387 (" 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)
5388 "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)
;
5389 // clean the altData cache and reset this to avoid wrong content length
5390 mAvailableCachedAltDataType.Truncate();
5391 StoreDeliveringAltData(false);
5392
5393 nsCOMPtr<nsICacheEntry> currentEntry;
5394 currentEntry.swap(mCacheEntry);
5395 rv = currentEntry->Recreate(dontPersist, getter_AddRefs(mCacheEntry));
5396 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5397 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)
;
5398 return NS_OK;
5399 }
5400
5401 StoreCacheEntryIsWriteOnly(true);
5402 }
5403
5404 // Set the expiration time for this cache entry
5405 rv = UpdateExpirationTime();
5406 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5407
5408 // mark this weakly framed until a response body is seen
5409 mCacheEntry->SetMetaDataElement("strongly-framed", "0");
5410
5411 rv = AddCacheEntryHeaders(mCacheEntry);
5412 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5413
5414 StoreInitedCacheEntry(true);
5415
5416 // Don't perform the check when writing (doesn't make sense)
5417 StoreConcurrentCacheAccess(0);
5418
5419 return NS_OK;
5420}
5421
5422void nsHttpChannel::UpdateInhibitPersistentCachingFlag() {
5423 // The no-store directive within the 'Cache-Control:' header indicates
5424 // that we must not store the response in a persistent cache.
5425 if (mResponseHead->NoStore()) {
5426 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
5427 return;
5428 }
5429
5430 if (!StaticPrefs::network_cache_persist_permanent_redirects_http() &&
5431 mURI->SchemeIs("http") &&
5432 nsHttp::IsPermanentRedirect(mResponseHead->Status())) {
5433 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
5434 return;
5435 }
5436
5437 // Only cache SSL content on disk if the pref is set
5438 if (!gHttpHandler->IsPersistentHttpsCachingEnabled() &&
5439 mURI->SchemeIs("https")) {
5440 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
5441 }
5442}
5443
5444nsresult DoAddCacheEntryHeaders(nsHttpChannel* self, nsICacheEntry* entry,
5445 nsHttpRequestHead* requestHead,
5446 nsHttpResponseHead* responseHead,
5447 nsITransportSecurityInfo* securityInfo) {
5448 nsresult rv;
5449
5450 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)
;
5451 // Store secure data in memory only
5452 if (securityInfo) {
5453 entry->SetSecurityInfo(securityInfo);
5454 }
5455
5456 // Store the HTTP request method with the cache entry so we can distinguish
5457 // for example GET and HEAD responses.
5458 nsAutoCString method;
5459 requestHead->Method(method);
5460 rv = entry->SetMetaDataElement("request-method", method.get());
5461 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5462
5463 // Store the HTTP authorization scheme used if any...
5464 rv = StoreAuthorizationMetaData(entry, requestHead);
5465 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5466
5467 // Iterate over the headers listed in the Vary response header, and
5468 // store the value of the corresponding request header so we can verify
5469 // that it has not varied when we try to re-use the cached response at
5470 // a later time. Take care to store "Cookie" headers only as hashes
5471 // due to security considerations and the fact that they can be pretty
5472 // large (bug 468426). We take care of "Vary: cookie" in ResponseWouldVary.
5473 //
5474 // NOTE: if "Vary: accept, cookie", then we will store the "accept" header
5475 // in the cache. we could try to avoid needlessly storing the "accept"
5476 // header in this case, but it doesn't seem worth the extra code to perform
5477 // the check.
5478 {
5479 nsAutoCString buf, metaKey;
5480 Unused << responseHead->GetHeader(nsHttp::Vary, buf);
5481
5482 constexpr auto prefix = "request-"_ns;
5483
5484 for (const nsACString& token :
5485 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
5486 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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] " "processing %s"
, self, nsPromiseFlatCString(token).get()); } } while (0)
5487 ("nsHttpChannel::AddCacheEntryHeaders [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::AddCacheEntryHeaders [this=%p] " "processing %s"
, self, nsPromiseFlatCString(token).get()); } } while (0)
5488 "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::AddCacheEntryHeaders [this=%p] " "processing %s"
, self, nsPromiseFlatCString(token).get()); } } while (0)
5489 self, 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::AddCacheEntryHeaders [this=%p] " "processing %s"
, self, nsPromiseFlatCString(token).get()); } } while (0)
;
5490 if (!token.EqualsLiteral("*")) {
5491 nsHttpAtom atom = nsHttp::ResolveAtom(token);
5492 nsAutoCString val;
5493 nsAutoCString hash;
5494 if (NS_SUCCEEDED(requestHead->GetHeader(atom, val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requestHead->GetHeader
(atom, val))), 1)))
) {
5495 // If cookie-header, store a hash of the value
5496 if (atom == nsHttp::Cookie) {
5497 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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] " "cookie-value %s"
, self, val.get()); } } while (0)
5498 ("nsHttpChannel::AddCacheEntryHeaders [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::AddCacheEntryHeaders [this=%p] " "cookie-value %s"
, self, val.get()); } } while (0)
5499 "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::AddCacheEntryHeaders [this=%p] " "cookie-value %s"
, self, val.get()); } } while (0)
5500 self, 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::AddCacheEntryHeaders [this=%p] " "cookie-value %s"
, self, val.get()); } } while (0)
;
5501 rv = Hash(val.get(), hash);
5502 // If hash failed, store a string not very likely
5503 // to be the result of subsequent hashes
5504 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5505 val = "<hash failed>"_ns;
5506 } else {
5507 val = hash;
5508 }
5509
5510 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)
;
5511 }
5512
5513 // build cache meta data key and set meta data element...
5514 metaKey = prefix + token;
5515 entry->SetMetaDataElement(metaKey.get(), val.get());
5516 } else {
5517 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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] " "clearing metadata for %s"
, self, nsPromiseFlatCString(token).get()); } } while (0)
5518 ("nsHttpChannel::AddCacheEntryHeaders [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::AddCacheEntryHeaders [this=%p] " "clearing metadata for %s"
, self, nsPromiseFlatCString(token).get()); } } while (0)
5519 "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::AddCacheEntryHeaders [this=%p] " "clearing metadata for %s"
, self, nsPromiseFlatCString(token).get()); } } while (0)
5520 self, 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::AddCacheEntryHeaders [this=%p] " "clearing metadata for %s"
, self, nsPromiseFlatCString(token).get()); } } while (0)
;
5521 metaKey = prefix + token;
5522 entry->SetMetaDataElement(metaKey.get(), nullptr);
5523 }
5524 }
5525 }
5526 }
5527
5528 // Store the received HTTP head with the cache entry as an element of
5529 // the meta data.
5530 nsAutoCString head;
5531 responseHead->Flatten(head, true);
5532 rv = entry->SetMetaDataElement("response-head", head.get());
5533 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5534 head.Truncate();
5535 responseHead->FlattenNetworkOriginalHeaders(head);
5536 rv = entry->SetMetaDataElement("original-response-headers", head.get());
5537 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5538
5539 // Indicate we have successfully finished setting metadata on the cache entry.
5540 rv = entry->MetaDataReady();
5541
5542 return rv;
5543}
5544
5545nsresult nsHttpChannel::AddCacheEntryHeaders(nsICacheEntry* entry) {
5546 return DoAddCacheEntryHeaders(this, entry, &mRequestHead, mResponseHead.get(),
5547 mSecurityInfo);
5548}
5549
5550inline void GetAuthType(const char* challenge, nsCString& authType) {
5551 const char* p;
5552
5553 // get the challenge type
5554 if ((p = strchr(challenge, ' ')) != nullptr) {
5555 authType.Assign(challenge, p - challenge);
5556 } else {
5557 authType.Assign(challenge);
5558 }
5559}
5560
5561nsresult StoreAuthorizationMetaData(nsICacheEntry* entry,
5562 nsHttpRequestHead* requestHead) {
5563 // Not applicable to proxy authorization...
5564 nsAutoCString val;
5565 if (NS_FAILED(requestHead->GetHeader(nsHttp::Authorization, val))((bool)(__builtin_expect(!!(NS_FAILED_impl(requestHead->GetHeader
(nsHttp::Authorization, val))), 0)))
) {
5566 return NS_OK;
5567 }
5568
5569 // eg. [Basic realm="wally world"]
5570 nsAutoCString buf;
5571 GetAuthType(val.get(), buf);
5572 return entry->SetMetaDataElement("auth", buf.get());
5573}
5574
5575// Finalize the cache entry
5576// - may need to rewrite response headers if any headers changed
5577// - may need to recalculate the expiration time if any headers changed
5578// - called only for freshly written cache entries
5579nsresult nsHttpChannel::FinalizeCacheEntry() {
5580 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)
;
5581
5582 // Don't update this meta-data on 304
5583 if (LoadStronglyFramed() && !mCachedContentIsValid && mCacheEntry) {
5584 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)
5585 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
5586 mCacheEntry->SetMetaDataElement("strongly-framed", "1");
5587 }
5588
5589 if (mResponseHead && LoadResponseHeadersModified()) {
5590 // Set the expiration time for this cache entry
5591 nsresult rv = UpdateExpirationTime();
5592 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5593 }
5594 return NS_OK;
5595}
5596
5597// Open an output stream to the cache entry and insert a listener tee into
5598// the chain of response listeners.
5599nsresult nsHttpChannel::InstallCacheListener(int64_t offset) {
5600 nsresult rv;
5601
5602 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)
;
5603
5604 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { *((volatile int*)__null) = 5604; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5605 MOZ_ASSERT(LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial
() || mRaceCacheWithNetwork)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadCacheEntryIsWriteOnly() ||
LoadCachedContentIsPartial() || mRaceCacheWithNetwork))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial() || mRaceCacheWithNetwork"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial() || mRaceCacheWithNetwork"
")"); do { *((volatile int*)__null) = 5606; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5606 mRaceCacheWithNetwork)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial
() || mRaceCacheWithNetwork)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadCacheEntryIsWriteOnly() ||
LoadCachedContentIsPartial() || mRaceCacheWithNetwork))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial() || mRaceCacheWithNetwork"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial() || mRaceCacheWithNetwork"
")"); do { *((volatile int*)__null) = 5606; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5607 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5607); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mListener" ")"
); do { *((volatile int*)__null) = 5607; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5608
5609 nsAutoCString contentEncoding, contentType;
5610 Unused << mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
5611 mResponseHead->ContentType(contentType);
5612 // If the content is compressible and the server has not compressed it,
5613 // mark the cache entry for compression.
5614 if (contentEncoding.IsEmpty() &&
5615 (contentType.EqualsLiteral(TEXT_HTML"text/html") ||
5616 contentType.EqualsLiteral(TEXT_PLAIN"text/plain") ||
5617 contentType.EqualsLiteral(TEXT_CSS"text/css") ||
5618 contentType.EqualsLiteral(TEXT_JAVASCRIPT"text/javascript") ||
5619 contentType.EqualsLiteral(TEXT_ECMASCRIPT"text/ecmascript") ||
5620 contentType.EqualsLiteral(TEXT_XML"text/xml") ||
5621 contentType.EqualsLiteral(APPLICATION_JAVASCRIPT"application/javascript") ||
5622 contentType.EqualsLiteral(APPLICATION_ECMASCRIPT"application/ecmascript") ||
5623 contentType.EqualsLiteral(APPLICATION_XJAVASCRIPT"application/x-javascript") ||
5624 contentType.EqualsLiteral(APPLICATION_XHTML_XML"application/xhtml+xml"))) {
5625 rv = mCacheEntry->SetMetaDataElement("uncompressed-len", "0");
5626 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5627 LOG(("unable to mark cache entry for compression"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "unable to mark cache entry for compression"); } } while (0
)
;
5628 }
5629 }
5630
5631 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)
;
5632
5633 // We must close the input stream first because cache entries do not
5634 // correctly handle having an output stream and input streams open at
5635 // the same time.
5636 mCacheInputStream.CloseAndRelease();
5637
5638 int64_t predictedSize = mResponseHead->TotalEntitySize();
5639 if (predictedSize != -1) {
5640 predictedSize -= offset;
5641 }
5642
5643 nsCOMPtr<nsIOutputStream> out;
5644 rv =
5645 mCacheEntry->OpenOutputStream(offset, predictedSize, getter_AddRefs(out));
5646 if (rv == NS_ERROR_NOT_AVAILABLE) {
5647 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)
;
5648 // Entry is already doomed.
5649 // This may happen when expiration time is set to past and the entry
5650 // has been removed by the background eviction logic.
5651 return NS_OK;
5652 }
5653 if (rv == NS_ERROR_FILE_TOO_BIG) {
5654 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)
5655 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
5656 mCacheEntry->AsyncDoom(nullptr);
5657 return NS_OK;
5658 }
5659 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5660
5661 if (LoadCacheOnlyMetadata()) {
5662 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
)
;
5663 // We must open and then close the output stream of the cache entry.
5664 // This way we indicate the content has been written (despite with zero
5665 // length) and the entry is now in the ready state with "having data".
5666
5667 out->Close();
5668 return NS_OK;
5669 }
5670
5671 // XXX disk cache does not support overlapped i/o yet
5672#if 0
5673 // Mark entry valid inorder to allow simultaneous reading...
5674 rv = mCacheEntry->MarkValid();
5675 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5676#endif
5677
5678 nsCOMPtr<nsIStreamListenerTee> tee =
5679 do_CreateInstance(kStreamListenerTeeCID, &rv);
5680 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5681
5682 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)
5683 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)
;
5684 rv = tee->Init(mListener, out, nullptr);
5685 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5686
5687 mListener = tee;
5688 return NS_OK;
5689}
5690
5691//-----------------------------------------------------------------------------
5692// nsHttpChannel <redirect>
5693//-----------------------------------------------------------------------------
5694
5695nsresult nsHttpChannel::SetupReplacementChannel(nsIURI* newURI,
5696 nsIChannel* newChannel,
5697 bool preserveMethod,
5698 uint32_t redirectFlags) {
5699 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
5700 ("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)
5701 "[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)
5702 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)
;
5703
5704 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
5705 mEndMarkerAdded = true;
5706
5707 nsAutoCString requestMethod;
5708 GetRequestMethod(requestMethod);
5709
5710 int32_t priority = PRIORITY_NORMAL;
5711 GetPriority(&priority);
5712
5713 TimingStruct timings;
5714 if (mTransaction) {
5715 timings = mTransaction->Timings();
5716 }
5717
5718 uint64_t size = 0;
5719 GetEncodedBodySize(&size);
5720
5721 nsAutoCString contentType;
5722 if (mResponseHead) {
5723 mResponseHead->ContentType(contentType);
5724 }
5725
5726 RefPtr<nsIIdentChannel> newIdentChannel = do_QueryObject(newChannel);
5727 uint64_t channelId = 0;
5728 if (newIdentChannel) {
5729 channelId = newIdentChannel->ChannelId();
5730 }
5731 profiler_add_network_marker(
5732 mURI, requestMethod, priority, mChannelId,
5733 NetworkLoadType::LOAD_REDIRECT, mLastStatusReported, TimeStamp::Now(),
5734 size, mCacheDisposition, mLoadInfo->GetInnerWindowID(),
5735 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), &timings,
5736 std::move(mSource), Some(nsDependentCString(contentType.get())), newURI,
5737 redirectFlags, channelId);
5738 }
5739
5740 nsresult rv = HttpBaseChannel::SetupReplacementChannel(
5741 newURI, newChannel, preserveMethod, redirectFlags);
5742 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5743
5744 nsAutoCString uriHost;
5745 mURI->GetAsciiHost(uriHost);
5746 // disable https-rr when encountering a downgrade from https to http.
5747 // If the host would have https-rr dns-entries, it would be misconfigured
5748 // due to giving us mixed signals:
5749 // 1. the signal to upgrade all http requests to https,
5750 // 2. but also downgrading to http on https via redirects.
5751 // Add to exclude list for that reason
5752 if (!gHttpHandler->IsHostExcludedForHTTPSRR(uriHost) &&
5753 nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
5754 mURI, newURI, mLoadInfo,
5755 {nsHTTPSOnlyUtils::UpgradeDowngradeEndlessLoopOptions::
5756 EnforceForHTTPSRR})) {
5757 // Add the host to a excluded list because:
5758 // 1. We don't need to do the same check again.
5759 // 2. Other subresources in the same host will be also excluded.
5760 gHttpHandler->ExcludeHTTPSRRHost(uriHost);
5761 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)
;
5762 }
5763
5764 rv = CheckRedirectLimit(newURI, redirectFlags);
5765 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5765); return rv; } } while (false)
;
5766
5767 // pass on the early hint observer to be able to process `103 Early Hints`
5768 // responses after cross origin redirects
5769 if (mEarlyHintObserver) {
5770 if (RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel)) {
5771 httpChannelImpl->SetEarlyHintObserver(mEarlyHintObserver);
5772 }
5773 mEarlyHintObserver = nullptr;
5774 }
5775
5776 // We don't support redirection for WebTransport for now.
5777 mWebTransportSessionEventListener = nullptr;
5778
5779 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
5780 if (!httpChannel) return NS_OK; // no other options to set
5781
5782 // convey the ApplyConversion flag (bug 91862)
5783 nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel);
5784 if (encodedChannel) encodedChannel->SetApplyConversion(LoadApplyConversion());
5785
5786 // transfer the resume information
5787 if (LoadResuming()) {
5788 nsCOMPtr<nsIResumableChannel> resumableChannel(
5789 do_QueryInterface(newChannel));
5790 if (!resumableChannel) {
5791 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Got asked to resume, but redirected to non-resumable channel!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5792)
5792 "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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5792)
;
5793 return NS_ERROR_NOT_RESUMABLE;
5794 }
5795 resumableChannel->ResumeAt(mStartPos, mEntityID);
5796 }
5797
5798 nsCOMPtr<nsIHttpChannelInternal> internalChannel =
5799 do_QueryInterface(newChannel, &rv);
5800 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5801 TimeStamp timestamp;
5802 rv = GetNavigationStartTimeStamp(&timestamp);
5803 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5803)
) {
5804 return rv;
5805 }
5806 if (timestamp) {
5807 Unused << internalChannel->SetNavigationStartTimeStamp(timestamp);
5808 }
5809 }
5810
5811 return NS_OK;
5812}
5813
5814nsresult nsHttpChannel::AsyncProcessRedirection(uint32_t redirectType) {
5815 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)
5816 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)
;
5817
5818 nsresult rv = ProcessCrossOriginSecurityHeaders();
5819 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5820 mStatus = rv;
5821 HandleAsyncAbort();
5822 return rv;
5823 }
5824
5825 nsAutoCString location;
5826
5827 // if a location header was not given, then we can't perform the redirect,
5828 // so just carry on as though this were a normal response.
5829 if (NS_FAILED(mResponseHead->GetHeader(nsHttp::Location, location))((bool)(__builtin_expect(!!(NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Location, location))), 0)))
) {
5830 return NS_ERROR_FAILURE;
5831 }
5832
5833 // If we were told to not follow redirects automatically, then again
5834 // carry on as though this were a normal response.
5835 if (mLoadInfo->GetDontFollowRedirects()) {
5836 return NS_ERROR_FAILURE;
5837 }
5838
5839 // make sure non-ASCII characters in the location header are escaped.
5840 nsAutoCString locationBuf;
5841 if (NS_EscapeURL(location.get(), -1, esc_OnlyNonASCII | esc_Spaces,
5842 locationBuf)) {
5843 location = locationBuf;
5844 }
5845
5846 mRedirectType = redirectType;
5847
5848 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)
5849 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)
;
5850
5851 rv = CreateNewURI(location.get(), getter_AddRefs(mRedirectURI));
5852
5853 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5854 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)
;
5855 return NS_ERROR_CORRUPTED_CONTENT;
5856 }
5857
5858 if (!StaticPrefs::network_allow_redirect_to_data() &&
5859 !mLoadInfo->GetAllowInsecureRedirectToDataURI() &&
5860 mRedirectURI->SchemeIs("data")) {
5861 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)
;
5862 nsContentSecurityManager::ReportBlockedDataURI(mRedirectURI, mLoadInfo,
5863 true);
5864 return NS_ERROR_DOM_BAD_URI;
5865 }
5866
5867 // Perform the URL query string stripping for redirects. We will only strip
5868 // the query string if it is redirecting to a third-party URI in the top
5869 // level.
5870 if (StaticPrefs::privacy_query_stripping_redirect()) {
5871 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
5872 bool isThirdPartyRedirectURI = true;
5873 thirdPartyUtil->IsThirdPartyURI(mURI, mRedirectURI,
5874 &isThirdPartyRedirectURI);
5875 if (isThirdPartyRedirectURI && mLoadInfo->GetExternalContentPolicyType() ==
5876 ExtContentPolicy::TYPE_DOCUMENT) {
5877 Telemetry::AccumulateCategorical(
5878 Telemetry::LABELS_QUERY_STRIPPING_COUNT::Redirect);
5879
5880 nsCOMPtr<nsIPrincipal> prin;
5881 ContentBlockingAllowList::RecomputePrincipal(
5882 mRedirectURI, mLoadInfo->GetOriginAttributes(), getter_AddRefs(prin));
5883
5884 bool isRedirectURIInAllowList = false;
5885 if (prin) {
5886 ContentBlockingAllowList::Check(prin, mPrivateBrowsing,
5887 isRedirectURIInAllowList);
5888 }
5889
5890 if (!isRedirectURIInAllowList) {
5891 nsCOMPtr<nsIURI> strippedURI;
5892
5893 nsCOMPtr<nsIURLQueryStringStripper> queryStripper;
5894 queryStripper =
5895 mozilla::components::URLQueryStringStripper::Service(&rv);
5896 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5896); return rv; } } while (false)
;
5897
5898 uint32_t numStripped;
5899
5900 rv = queryStripper->Strip(mRedirectURI, mPrivateBrowsing,
5901 getter_AddRefs(strippedURI), &numStripped);
5902 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5902); return rv; } } while (false)
;
5903
5904 if (numStripped) {
5905 mUnstrippedRedirectURI = mRedirectURI;
5906 mRedirectURI = strippedURI;
5907
5908 // Record telemetry, but only if we stripped any query params.
5909 Telemetry::AccumulateCategorical(
5910 Telemetry::LABELS_QUERY_STRIPPING_COUNT::StripForRedirect);
5911 Telemetry::Accumulate(Telemetry::QUERY_STRIPPING_PARAM_COUNT,
5912 numStripped);
5913 }
5914 }
5915 }
5916 }
5917
5918 if (NS_WARN_IF(!mRedirectURI)NS_warn_if_impl(!mRedirectURI, "!mRedirectURI", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5918)
) {
5919 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)
;
5920 return NS_ERROR_FAILURE;
5921 }
5922
5923 return ContinueProcessRedirectionAfterFallback(NS_OK);
5924}
5925
5926nsresult nsHttpChannel::ContinueProcessRedirectionAfterFallback(nsresult rv) {
5927 // Kill the current cache entry if we are redirecting
5928 // back to ourself.
5929 bool redirectingBackToSameURI = false;
5930 if (mCacheEntry && LoadCacheEntryIsWriteOnly() &&
5931 NS_SUCCEEDED(mURI->Equals(mRedirectURI, &redirectingBackToSameURI))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mURI->Equals(mRedirectURI
, &redirectingBackToSameURI))), 1)))
&&
5932 redirectingBackToSameURI) {
5933 mCacheEntry->AsyncDoom(nullptr);
5934 }
5935
5936 // move the reference of the old location to the new one if the new
5937 // one has none.
5938 PropagateReferenceIfNeeded(mURI, mRedirectURI);
5939
5940 bool rewriteToGET =
5941 ShouldRewriteRedirectToGET(mRedirectType, mRequestHead.ParsedMethod());
5942
5943 // prompt if the method is not safe (such as POST, PUT, DELETE, ...)
5944 if (!rewriteToGET && !mRequestHead.IsSafeMethod()) {
5945 rv = PromptTempRedirect();
5946 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5947 }
5948
5949 uint32_t redirectFlags;
5950 if (nsHttp::IsPermanentRedirect(mRedirectType)) {
5951 redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
5952 } else {
5953 redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
5954 }
5955
5956 nsCOMPtr<nsIIOService> ioService;
5957 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
5958 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5959
5960 nsCOMPtr<nsIChannel> newChannel;
5961 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
5962 CloneLoadInfoForRedirect(mRedirectURI, redirectFlags);
5963
5964 // Propagate the unstripped redirect URI.
5965 redirectLoadInfo->SetUnstrippedURI(mUnstrippedRedirectURI);
5966
5967 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), mRedirectURI,
5968 redirectLoadInfo,
5969 nullptr, // PerformanceStorage
5970 nullptr, // aLoadGroup
5971 nullptr, // aCallbacks
5972 nsIRequest::LOAD_NORMAL, ioService);
5973 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 5973); return rv; } } while (false)
;
5974
5975 rv = SetupReplacementChannel(mRedirectURI, newChannel, !rewriteToGET,
5976 redirectFlags);
5977 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5978
5979 // verify that this is a legal redirect
5980 mRedirectChannel = newChannel;
5981
5982 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
5983 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, redirectFlags);
5984
5985 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
5986
5987 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5988 AutoRedirectVetoNotifier notifier(this, rv);
5989 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
5990 }
5991
5992 return rv;
5993}
5994
5995nsresult nsHttpChannel::ContinueProcessRedirection(nsresult rv) {
5996 AutoRedirectVetoNotifier notifier(this, rv);
5997
5998 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)
5999 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)
;
6000 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6001
6002 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRedirectChannel"
") (" "No redirect channel?" ")"); do { *((volatile int*)__null
) = 6002; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
6003
6004 // Make sure to do this after we received redirect veto answer,
6005 // i.e. after all sinks had been notified
6006 mRedirectChannel->SetOriginalURI(mOriginalURI);
6007
6008 // XXX we used to talk directly with the script security manager, but that
6009 // should really be handled by the event sink implementation.
6010
6011 // begin loading the new channel
6012 rv = mRedirectChannel->AsyncOpen(mListener);
6013 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)
;
6014 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6014); return rv; } } while (false)
;
6015
6016 // close down this channel
6017 Cancel(NS_BINDING_REDIRECTED);
6018
6019 notifier.RedirectSucceeded();
6020
6021 ReleaseListeners();
6022
6023 return NS_OK;
6024}
6025
6026//-----------------------------------------------------------------------------
6027// nsHttpChannel <auth>
6028//-----------------------------------------------------------------------------
6029
6030NS_IMETHODIMPnsresult nsHttpChannel::OnAuthAvailable() {
6031 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)
;
6032
6033 // setting mAuthRetryPending flag and resuming the transaction
6034 // triggers process of throwing away the unauthenticated data already
6035 // coming from the network
6036 mIsAuthChannel = true;
6037 mAuthRetryPending = true;
6038 StoreProxyAuthPending(false);
6039 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)
;
6040 if (mTransactionPump) {
6041 mTransactionPump->Resume();
6042 }
6043
6044 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
6045 return CallOrWaitForResume(
6046 [](auto* self) { return self->RedirectToNewChannelForAuthRetry(); });
6047 }
6048
6049 return NS_OK;
6050}
6051
6052NS_IMETHODIMPnsresult nsHttpChannel::OnAuthCancelled(bool userCancel) {
6053 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)
;
6054 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthRetryPending"
") (" "OnAuthCancelled should not be called twice" ")"); do {
*((volatile int*)__null) = 6054; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6055
6056 if (mTransactionPump) {
6057 // If the channel is trying to authenticate to a proxy and
6058 // that was canceled we cannot show the http response body
6059 // from the 40x as that might mislead the user into thinking
6060 // it was a end host response instead of a proxy reponse.
6061 // This must check explicitly whether a proxy auth was being done
6062 // because we do want to show the content if this is an error from
6063 // the origin server.
6064 if (LoadProxyAuthPending()) Cancel(NS_ERROR_PROXY_CONNECTION_REFUSED);
6065
6066 // Make sure to process security headers before calling CallOnStartRequest.
6067 nsresult rv = ProcessCrossOriginSecurityHeaders();
6068 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6069 mStatus = rv;
6070 HandleAsyncAbort();
6071 return rv;
6072 }
6073
6074 // ensure call of OnStartRequest of the current listener here,
6075 // it would not be called otherwise at all
6076 rv = CallOnStartRequest();
6077
6078 // drop mAuthRetryPending flag and resume the transaction
6079 // this resumes load of the unauthenticated content data (which
6080 // may have been canceled if we don't want to show it)
6081 mAuthRetryPending = false;
6082 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)
;
6083 mTransactionPump->Resume();
6084
6085 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) mTransactionPump->Cancel(rv);
6086 }
6087
6088 StoreProxyAuthPending(false);
6089 return NS_OK;
6090}
6091
6092NS_IMETHODIMPnsresult nsHttpChannel::CloseStickyConnection() {
6093 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)
;
6094
6095 // Require we are between OnStartRequest and OnStopRequest, because
6096 // what we do here takes effect in OnStopRequest (not reusing the
6097 // connection for next authentication round).
6098 if (!LoadIsPending()) {
6099 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)
;
6100 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6102); MOZ_PretendNoReturn(); } while (0)
6101 "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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6102); MOZ_PretendNoReturn(); } while (0)
6102 "effect")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6102); MOZ_PretendNoReturn(); } while (0)
;
6103 return NS_ERROR_UNEXPECTED;
6104 }
6105
6106 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { *((volatile int*)__null) = 6106; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6107 if (!mTransaction) {
6108 return NS_ERROR_UNEXPECTED;
6109 }
6110
6111 if (!(mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
6112 mTransaction->HasStickyConnection())) {
6113 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)
;
6114 return NS_OK;
6115 }
6116
6117 mTransaction->DontReuseConnection();
6118 return NS_OK;
6119}
6120
6121NS_IMETHODIMPnsresult nsHttpChannel::ConnectionRestartable(bool aRestartable) {
6122 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)
6123 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)
;
6124 StoreAuthConnectionRestartable(aRestartable);
6125 return NS_OK;
6126}
6127
6128//-----------------------------------------------------------------------------
6129// nsHttpChannel::nsISupports
6130//-----------------------------------------------------------------------------
6131
6132NS_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; }
6133NS_IMPL_RELEASE_INHERITED(nsHttpChannel, HttpBaseChannel)MozExternalRefCountType nsHttpChannel::Release(void) { nsrefcnt
r = HttpBaseChannel::Release(); if constexpr (::mozilla::detail
::ShouldLogInheritedRefcnt<nsHttpChannel>) { NS_LogRelease
((this), (r), ("nsHttpChannel")); } return r; }
6134
6135NS_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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6135); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
6136 NS_INTERFACE_MAP_ENTRY(nsIRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequest>)) foundInterface = static_cast
<nsIRequest*>(this); else
6137 NS_INTERFACE_MAP_ENTRY(nsIChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIChannel>)) foundInterface = static_cast
<nsIChannel*>(this); else
6138 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestObserver>)) foundInterface
= static_cast<nsIRequestObserver*>(this); else
6139 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIStreamListener>)) foundInterface
= static_cast<nsIStreamListener*>(this); else
6140 NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannel>)) foundInterface =
static_cast<nsIHttpChannel*>(this); else
6141 NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheInfoChannel>)) foundInterface
= static_cast<nsICacheInfoChannel*>(this); else
6142 NS_INTERFACE_MAP_ENTRY(nsICachingChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICachingChannel>)) foundInterface
= static_cast<nsICachingChannel*>(this); else
6143 NS_INTERFACE_MAP_ENTRY(nsIClassOfService)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIClassOfService>)) foundInterface
= static_cast<nsIClassOfService*>(this); else
6144 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel>)) foundInterface
= static_cast<nsIUploadChannel*>(this); else
6145 NS_INTERFACE_MAP_ENTRY(nsIFormPOSTActionChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIFormPOSTActionChannel>)) foundInterface
= static_cast<nsIFormPOSTActionChannel*>(this); else
6146 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel2>)) foundInterface
= static_cast<nsIUploadChannel2*>(this); else
6147 NS_INTERFACE_MAP_ENTRY(nsICacheEntryOpenCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheEntryOpenCallback>)) foundInterface
= static_cast<nsICacheEntryOpenCallback*>(this); else
6148 NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannelInternal>)) foundInterface
= static_cast<nsIHttpChannelInternal*>(this); else
6149 NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIResumableChannel>)) foundInterface
= static_cast<nsIResumableChannel*>(this); else
6150 NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsITransportEventSink>)) foundInterface
= static_cast<nsITransportEventSink*>(this); else
6151 NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsPriority>)) foundInterface
= static_cast<nsISupportsPriority*>(this); else
6152 NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProtocolProxyCallback>)) foundInterface
= static_cast<nsIProtocolProxyCallback*>(this); else
6153 NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProxiedChannel>)) foundInterface
= static_cast<nsIProxiedChannel*>(this); else
6154 NS_INTERFACE_MAP_ENTRY(nsIHttpAuthenticableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpAuthenticableChannel>)) foundInterface
= static_cast<nsIHttpAuthenticableChannel*>(this); else
6155 NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAsyncVerifyRedirectCallback>))
foundInterface = static_cast<nsIAsyncVerifyRedirectCallback
*>(this); else
6156 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableRequest>)) foundInterface
= static_cast<nsIThreadRetargetableRequest*>(this); else
6157 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableStreamListener>
)) foundInterface = static_cast<nsIThreadRetargetableStreamListener
*>(this); else
6158 NS_INTERFACE_MAP_ENTRY(nsIDNSListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDNSListener>)) foundInterface =
static_cast<nsIDNSListener*>(this); else
6159 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
6160 NS_INTERFACE_MAP_ENTRY(nsICorsPreflightCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICorsPreflightCallback>)) foundInterface
= static_cast<nsICorsPreflightCallback*>(this); else
6161 NS_INTERFACE_MAP_ENTRY(nsIRaceCacheWithNetwork)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRaceCacheWithNetwork>)) foundInterface
= static_cast<nsIRaceCacheWithNetwork*>(this); else
6162 NS_INTERFACE_MAP_ENTRY(nsIRequestTailUnblockCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestTailUnblockCallback>)) foundInterface
= static_cast<nsIRequestTailUnblockCallback*>(this); else
6163 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
6164 NS_INTERFACE_MAP_ENTRY(nsIEarlyHintObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIEarlyHintObserver>)) foundInterface
= static_cast<nsIEarlyHintObserver*>(this); else
6165NS_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; }
6166
6167//-----------------------------------------------------------------------------
6168// nsHttpChannel::nsIRequest
6169//-----------------------------------------------------------------------------
6170
6171NS_IMETHODIMPnsresult nsHttpChannel::SetCanceledReason(const nsACString& aReason) {
6172 return SetCanceledReasonImpl(aReason);
6173}
6174
6175NS_IMETHODIMPnsresult nsHttpChannel::GetCanceledReason(nsACString& aReason) {
6176 return GetCanceledReasonImpl(aReason);
6177}
6178
6179NS_IMETHODIMPnsresult
6180nsHttpChannel::CancelWithReason(nsresult aStatus, const nsACString& aReason) {
6181 return CancelWithReasonImpl(aStatus, aReason);
6182}
6183
6184NS_IMETHODIMPnsresult
6185nsHttpChannel::Cancel(nsresult status) {
6186 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6186); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 6186; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6187 // We should never have a pump open while a CORS preflight is in progress.
6188 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6188); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { *((volatile int*)__null) = 6188; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6189#ifdef DEBUG1
6190 // We want to perform this check only when the chanel is being cancelled the
6191 // first time with a URL classifier blocking error code. If mStatus is
6192 // already set to such an error code then Cancel() may be called for some
6193 // other reason, for example because we've received notification about our
6194 // parent process side channel being canceled, in which case we cannot expect
6195 // that CancelByURLClassifier() would have handled this case.
6196 if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(status) &&
6197 !UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(mStatus)) {
6198 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("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6200, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
6199 " 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("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6200, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
6200 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("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6200, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
;
6201 }
6202#endif
6203
6204 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)
6205 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)
;
6206 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(!AllowedErrorForHTTPSRRFallback(status))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!AllowedErrorForHTTPSRRFallback(status)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!AllowedErrorForHTTPSRRFallback(status)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForHTTPSRRFallback(status)"
")"); do { *((volatile int*)__null) = 6208; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6207 NS_SUCCEEDED(mStatus),do { if (!(mConnectionInfo && mConnectionInfo->UsingConnect
()) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus
)), 1)))) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!AllowedErrorForHTTPSRRFallback(status))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!AllowedErrorForHTTPSRRFallback(status)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!AllowedErrorForHTTPSRRFallback(status)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForHTTPSRRFallback(status)"
")"); do { *((volatile int*)__null) = 6208; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6208 !AllowedErrorForHTTPSRRFallback(status))do { if (!(mConnectionInfo && mConnectionInfo->UsingConnect
()) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus
)), 1)))) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!AllowedErrorForHTTPSRRFallback(status))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!AllowedErrorForHTTPSRRFallback(status)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!AllowedErrorForHTTPSRRFallback(status)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForHTTPSRRFallback(status)"
")"); do { *((volatile int*)__null) = 6208; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6209
6210 mEarlyHintObserver = nullptr;
6211 mWebTransportSessionEventListener = nullptr;
6212
6213 if (mCanceled) {
6214 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)
;
6215 return NS_OK;
6216 }
6217
6218 LogCallingScriptLocation(this);
6219
6220 if (LoadWaitingForRedirectCallback()) {
6221 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)
;
6222 }
6223
6224 return CancelInternal(status);
6225}
6226
6227NS_IMETHODIMPnsresult
6228nsHttpChannel::CancelByURLClassifier(nsresult aErrorCode) {
6229 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { *((volatile int*)__null) = 6230; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6230 UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { *((volatile int*)__null) = 6230; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6231 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 6231; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6232 // We should never have a pump open while a CORS preflight is in progress.
6233 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { *((volatile int*)__null) = 6233; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6234
6235 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)
;
6236
6237 if (mCanceled) {
6238 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)
;
6239 return NS_OK;
6240 }
6241
6242 // We are being canceled by the channel classifier because of tracking
6243 // protection, but we haven't yet had a chance to dispatch the
6244 // "http-on-modify-request" notifications yet (this would normally be
6245 // done in PrepareToConnect()). So do that now, before proceeding to
6246 // cancel.
6247 //
6248 // Note that running these observers can itself result in the channel
6249 // being canceled. In that case, we accept that cancelation code as
6250 // the cause of the cancelation, as if the classification of the channel
6251 // would have occurred past this point!
6252
6253 // notify "http-on-modify-request" observers
6254 CallOnModifyRequestObservers();
6255
6256 // Check if request was cancelled during on-modify-request
6257 if (mCanceled) {
6258 return mStatus;
6259 }
6260
6261 if (mSuspendCount) {
6262 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)
;
6263 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6263); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
")"); do { *((volatile int*)__null) = 6263; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6264 StoreChannelClassifierCancellationPending(1);
6265 mCallOnResume = [aErrorCode](nsHttpChannel* self) {
6266 self->HandleContinueCancellingByURLClassifier(aErrorCode);
6267 return NS_OK;
6268 };
6269 return NS_OK;
6270 }
6271
6272 // Check to see if we should redirect this channel elsewhere by
6273 // nsIHttpChannel.redirectTo API request
6274 if (mAPIRedirectToURI) {
6275 StoreChannelClassifierCancellationPending(1);
6276 return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
6277 }
6278
6279 return CancelInternal(aErrorCode);
6280}
6281
6282void nsHttpChannel::ContinueCancellingByURLClassifier(nsresult aErrorCode) {
6283 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6284); AnnotateMozCrashReason("MOZ_ASSERT" "(" "UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { *((volatile int*)__null) = 6284; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6284 UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6284); AnnotateMozCrashReason("MOZ_ASSERT" "(" "UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { *((volatile int*)__null) = 6284; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6285 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6285); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 6285; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6286 // We should never have a pump open while a CORS preflight is in progress.
6287 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { *((volatile int*)__null) = 6287; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6288
6289 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)
;
6290 if (mCanceled) {
6291 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)
;
6292 return;
6293 }
6294
6295 // Check to see if we should redirect this channel elsewhere by
6296 // nsIHttpChannel.redirectTo API request
6297 if (mAPIRedirectToURI) {
6298 Unused << AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
6299 return;
6300 }
6301
6302 Unused << CancelInternal(aErrorCode);
6303}
6304
6305nsresult nsHttpChannel::CancelInternal(nsresult status) {
6306 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)
;
6307 bool channelClassifierCancellationPending =
6308 !!LoadChannelClassifierCancellationPending();
6309 if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(status)) {
6310 StoreChannelClassifierCancellationPending(0);
6311 }
6312
6313 mEarlyHintObserver = nullptr;
6314 mWebTransportSessionEventListener = nullptr;
6315 mCanceled = true;
6316 mStatus = NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) ? status : NS_ERROR_ABORT;
6317
6318 if (StaticPrefs::network_http_network_error_logging_enabled() &&
6319 LoadUsedNetwork() && !mReportedNEL) {
6320 if (nsCOMPtr<nsINetworkErrorLogging> nel =
6321 components::NetworkErrorLogging::Service()) {
6322 nel->GenerateNELReport(this);
6323 }
6324 mReportedNEL = true;
6325 }
6326
6327 // We don't want the content process to see any header values
6328 // when the request is blocked by ORB
6329 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref) {
6330 mResponseHead->ClearHeaders();
6331 }
6332
6333 if (mLastStatusReported && !mEndMarkerAdded &&
6334 profiler_thread_is_being_profiled_for_markers()) {
6335 // These do allocations/frees/etc; avoid if not active
6336 // mLastStatusReported can be null if Cancel is called before we added the
6337 // start marker.
6338 mEndMarkerAdded = true;
6339
6340 nsAutoCString requestMethod;
6341 GetRequestMethod(requestMethod);
6342
6343 int32_t priority = PRIORITY_NORMAL;
6344 GetPriority(&priority);
6345
6346 uint64_t size = 0;
6347 GetEncodedBodySize(&size);
6348
6349 profiler_add_network_marker(
6350 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_CANCEL,
6351 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
6352 mLoadInfo->GetInnerWindowID(),
6353 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(),
6354 &mTransactionTimings, std::move(mSource));
6355 }
6356
6357 // If we don't have mTransactionPump and mCachePump, we need to call
6358 // AsyncAbort to make sure this channel's listener got notified.
6359 bool needAsyncAbort = !mTransactionPump && !mCachePump;
6360
6361 if (mProxyRequest) mProxyRequest->Cancel(status);
6362 CancelNetworkRequest(status);
6363 mCacheInputStream.CloseAndRelease();
6364 if (mCachePump) mCachePump->Cancel(status);
6365 if (mAuthProvider) mAuthProvider->Cancel(status);
6366 if (mPreflightChannel) mPreflightChannel->Cancel(status);
6367 if (mRequestContext && mOnTailUnblock) {
6368 mOnTailUnblock = nullptr;
6369 mRequestContext->CancelTailedRequest(this);
6370 CloseCacheEntry(false);
6371 needAsyncAbort = false;
6372 Unused << AsyncAbort(status);
6373 } else if (channelClassifierCancellationPending) {
6374 // If mCallOnResume is not null here, it's set in
6375 // nsHttpChannel::CancelByURLClassifier. We can override mCallOnResume since
6376 // mCanceled is true and nsHttpChannel::ContinueCancellingByURLClassifier
6377 // does nothing.
6378 if (mCallOnResume) {
6379 mCallOnResume = nullptr;
6380 }
6381 // If we're coming from an asynchronous path when canceling a channel due
6382 // to safe-browsing protection, we need to AsyncAbort the channel now.
6383 needAsyncAbort = false;
6384 Unused << AsyncAbort(status);
6385 }
6386
6387 // If we already have mCallOnResume, AsyncAbort will be called in
6388 // ResumeInternal.
6389 if (needAsyncAbort && !mCallOnResume && !mSuspendCount) {
6390 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)
;
6391 CloseCacheEntry(false);
6392 Unused << AsyncAbort(status);
6393 }
6394 return NS_OK;
6395}
6396
6397void nsHttpChannel::CancelNetworkRequest(nsresult aStatus) {
6398 if (mTransaction) {
6399 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, aStatus);
6400 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6401 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)
;
6402 }
6403 }
6404 if (mTransactionPump) mTransactionPump->Cancel(aStatus);
6405
6406 mEarlyHintObserver = nullptr;
6407 mWebTransportSessionEventListener = nullptr;
6408}
6409
6410NS_IMETHODIMPnsresult
6411nsHttpChannel::Suspend() {
6412 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6412); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
6413
6414 LOG(("nsHttpChannel::SuspendInternal [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::SuspendInternal [this=%p]\n", this); } } while
(0)
;
6415 LogCallingScriptLocation(this);
6416
6417 ++mSuspendCount;
6418
6419 if (mSuspendCount == 1) {
6420 mSuspendTimestamp = TimeStamp::NowLoRes();
6421 }
6422
6423 nsresult rvTransaction = NS_OK;
6424 if (mTransactionPump) {
6425 rvTransaction = mTransactionPump->Suspend();
6426 }
6427 nsresult rvCache = NS_OK;
6428 if (mCachePump) {
6429 rvCache = mCachePump->Suspend();
6430 }
6431
6432 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
6433}
6434
6435NS_IMETHODIMPnsresult
6436nsHttpChannel::Resume() {
6437 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6437); return NS_ERROR_UNEXPECTED; } } while (false)
;
6438
6439 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)
;
6440 LogCallingScriptLocation(this);
6441
6442 if (--mSuspendCount == 0) {
6443 mSuspendTotalTime += TimeStamp::NowLoRes() - mSuspendTimestamp;
6444
6445 if (mCallOnResume) {
6446 // Resume the interrupted procedure first, then resume
6447 // the pump to continue process the input stream.
6448 // Any newly created pump MUST be suspended to prevent calling
6449 // its OnStartRequest before OnStopRequest of any pre-existing
6450 // pump. AsyncResumePending ensures that.
6451 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadAsyncResumePending()"
")"); do { *((volatile int*)__null) = 6451; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6452 StoreAsyncResumePending(1);
6453
6454 std::function<nsresult(nsHttpChannel*)> callOnResume = nullptr;
6455 std::swap(callOnResume, mCallOnResume);
6456
6457 RefPtr<nsHttpChannel> self(this);
6458 nsCOMPtr<nsIRequest> transactionPump = mTransactionPump;
6459 RefPtr<nsInputStreamPump> cachePump = mCachePump;
6460
6461 nsresult rv = NS_DispatchToCurrentThread(NS_NewRunnableFunction(
6462 "nsHttpChannel::CallOnResume",
6463 [callOnResume{std::move(callOnResume)}, self{std::move(self)},
6464 transactionPump{std::move(transactionPump)},
6465 cachePump{std::move(cachePump)}]() {
6466 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()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { *((volatile int*)__null) = 6466; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6467 nsresult rv = self->CallOrWaitForResume(callOnResume);
6468 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6469 self->CloseCacheEntry(false);
6470 Unused << self->AsyncAbort(rv);
6471 }
6472 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()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6472); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { *((volatile int*)__null) = 6472; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6473
6474 self->StoreAsyncResumePending(0);
6475
6476 // And now actually resume the previously existing pumps.
6477 if (transactionPump) {
6478 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
6479 ("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)
6480 "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)
6481 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)
;
6482 transactionPump->Resume();
6483 }
6484 if (cachePump) {
6485 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
6486 ("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)
6487 "%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)
6488 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)
;
6489 cachePump->Resume();
6490 }
6491
6492 // Any newly created pumps were suspended once because of
6493 // AsyncResumePending. Problem is that the stream listener
6494 // notification is already pending in the queue right now, because
6495 // AsyncRead doesn't (regardless if called after Suspend) respect
6496 // the suspend coutner and the right order would not be preserved.
6497 // Hence, we do another dispatch round to actually Resume after
6498 // the notification from the original pump.
6499 if (transactionPump != self->mTransactionPump &&
6500 self->mTransactionPump) {
6501 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
6502 ("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)
6503 "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)
6504 "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)
6505 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)
;
6506
6507 nsCOMPtr<nsIRequest> pump = self->mTransactionPump;
6508 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
6509 "nsHttpChannel::CallOnResume new transaction",
6510 [pump{std::move(pump)}]() { pump->Resume(); }));
6511 }
6512 if (cachePump != self->mCachePump && self->mCachePump) {
6513 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
6514 ("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)
6515 "%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)
6516 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)
;
6517
6518 RefPtr<nsInputStreamPump> pump = self->mCachePump;
6519 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
6520 "nsHttpChannel::CallOnResume new pump",
6521 [pump{std::move(pump)}]() { pump->Resume(); }));
6522 }
6523 }));
6524 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6524); return rv; } } while (false)
;
6525 return rv;
6526 }
6527 }
6528
6529 nsresult rvTransaction = NS_OK;
6530 if (mTransactionPump) {
6531 rvTransaction = mTransactionPump->Resume();
6532 }
6533
6534 nsresult rvCache = NS_OK;
6535 if (mCachePump) {
6536 rvCache = mCachePump->Resume();
6537 }
6538
6539 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
6540}
6541
6542//-----------------------------------------------------------------------------
6543// nsHttpChannel::nsIChannel
6544//-----------------------------------------------------------------------------
6545
6546NS_IMETHODIMPnsresult
6547nsHttpChannel::GetSecurityInfo(nsITransportSecurityInfo** securityInfo) {
6548 NS_ENSURE_ARG_POINTER(securityInfo)do { if ((__builtin_expect(!!(!(securityInfo)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "securityInfo" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6548); return NS_ERROR_INVALID_POINTER; } } while (false)
;
6549 *securityInfo = do_AddRef(mSecurityInfo).take();
6550 return NS_OK;
6551}
6552
6553// If any of the functions that AsyncOpen calls returns immediately an error
6554// AsyncAbort(which calls onStart/onStopRequest) does not need to be call.
6555// To be sure that they are not call ReleaseListeners() is called.
6556// If AsyncOpen returns NS_OK, after that point AsyncAbort must be called on
6557// any error.
6558NS_IMETHODIMPnsresult
6559nsHttpChannel::AsyncOpen(nsIStreamListener* aListener) {
6560 nsCOMPtr<nsIStreamListener> listener = aListener;
6561 nsresult rv =
6562 nsContentSecurityManager::doContentSecurityCheck(this, listener);
6563 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6563)
) {
6564 ReleaseListeners();
6565 return rv;
6566 }
6567
6568 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6575); 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 { *((volatile int*)__null) = 6575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6569 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6575); 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 { *((volatile int*)__null) = 6575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6570 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6575); 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 { *((volatile int*)__null) = 6575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6571 (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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6575); 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 { *((volatile int*)__null) = 6575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6572 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6575); 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 { *((volatile int*)__null) = 6575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6573 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6575); 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 { *((volatile int*)__null) = 6575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6574 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6575); 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 { *((volatile int*)__null) = 6575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6575 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6575); 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 { *((volatile int*)__null) = 6575; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6576
6577 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
)
;
6578 mOpenerCallingScriptLocation = CallingScriptLocationString();
6579 LogCallingScriptLocation(this, mOpenerCallingScriptLocation);
6580 NS_CompareLoadInfoAndLoadContext(this);
6581
6582#ifdef DEBUG1
6583 AssertPrivateBrowsingId();
6584#endif
6585
6586 NS_ENSURE_ARG_POINTER(listener)do { if ((__builtin_expect(!!(!(listener)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "listener" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6586); return NS_ERROR_INVALID_POINTER; } } while (false)
;
6587 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6587); return NS_ERROR_IN_PROGRESS; } } while (false)
;
6588 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6588); return NS_ERROR_ALREADY_OPENED; } } while (false)
;
6589
6590 if (mCanceled) {
6591 ReleaseListeners();
6592 return NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) ? mStatus : NS_ERROR_FAILURE;
6593 }
6594
6595 if (MaybeWaitForUploadStreamNormalization(listener, nullptr)) {
6596 return NS_OK;
6597 }
6598
6599 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6599); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 6599; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6600
6601 if (!gHttpHandler->Active()) {
6602 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)
;
6603 ReleaseListeners();
6604 return NS_ERROR_NOT_AVAILABLE;
6605 }
6606
6607 rv = NS_CheckPortSafety(mURI);
6608 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6609 ReleaseListeners();
6610 return rv;
6611 }
6612
6613 // If no one called SetLoadGroup or SetNotificationCallbacks, the private
6614 // state has not been updated on PrivateBrowsingChannel (which we derive
6615 // from) Same if the loadinfo has changed since the creation of the channel.
6616 // Hence, we have to call UpdatePrivateBrowsing() here
6617 UpdatePrivateBrowsing();
6618
6619 AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(this);
6620
6621 // Recalculate the default userAgent header after the AntiTrackingInfo gets
6622 // updated because we can only know whether the site is exempted from
6623 // fingerprinting protection after we have the AntiTracking Info.
6624 //
6625 // Note that we don't recalculate the header if it has been modified since the
6626 // channel was created because we want to preserve the modified header.
6627 if (!LoadIsUserAgentHeaderModified()) {
6628 rv = mRequestHead.SetHeader(
6629 nsHttp::User_Agent,
6630 gHttpHandler->UserAgent(nsContentUtils::ShouldResistFingerprinting(
6631 this, RFPTarget::HttpUserAgent)),
6632 false, nsHttpHeaderArray::eVarietyRequestEnforceDefault);
6633 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 6633; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6634 }
6635
6636 if (WaitingForTailUnblock()) {
6637 // This channel is marked as Tail and is part of a request context
6638 // that has positive number of non-tailed requestst, hence this channel
6639 // has been put to a queue.
6640 // When tail is unblocked, OnTailUnblock on this channel will be called
6641 // to continue AsyncOpen.
6642 mListener = listener;
6643 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6643); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { *((volatile int*)__null) = 6643; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6644 mOnTailUnblock = &nsHttpChannel::AsyncOpenOnTailUnblock;
6645
6646 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)
;
6647 return NS_OK;
6648 }
6649
6650 // Remember the cookie header that was set, if any
6651 nsAutoCString cookieHeader;
6652 if (NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::Cookie, cookieHeader))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::Cookie, cookieHeader))), 1)))
) {
6653 mUserSetCookieHeader = cookieHeader;
6654 }
6655
6656 // Set user agent override, do so before OnOpeningRequest notification
6657 // since we want to allow consumers of that notification change or remove
6658 // the User-Agent request header.
6659 HttpBaseChannel::SetDocshellUserAgentOverride();
6660
6661 // After we notify any observers (on-opening-request, loadGroup, etc) we
6662 // must return NS_OK and return any errors asynchronously via
6663 // OnStart/OnStopRequest. Observers may add a reference to the channel
6664 // and expect to get OnStopRequest so they know when to drop the reference,
6665 // etc.
6666
6667 // notify "http-on-opening-request" observers, but not if this is a redirect
6668 if (!(mLoadFlags & LOAD_REPLACE)) {
6669 gHttpHandler->OnOpeningRequest(this);
6670 }
6671
6672 StoreIsPending(true);
6673 StoreWasOpened(true);
6674
6675 mListener = listener;
6676
6677 if (nsIOService::UseSocketProcess() &&
6678 !gIOService->IsSocketProcessLaunchComplete()) {
6679 RefPtr<nsHttpChannel> self = this;
6680 gIOService->CallOrWaitForSocketProcess(
6681 [self]() { self->AsyncOpenFinal(TimeStamp::Now()); });
6682 return NS_OK;
6683 }
6684
6685 AsyncOpenFinal(TimeStamp::Now());
6686
6687 return NS_OK;
6688}
6689
6690void nsHttpChannel::AsyncOpenFinal(TimeStamp aTimeStamp) {
6691 // We save this timestamp from outside of the if block in case we enable the
6692 // profiler after AsyncOpen().
6693 mLastStatusReported = TimeStamp::Now();
6694 if (profiler_thread_is_being_profiled_for_markers()) {
6695 nsAutoCString requestMethod;
6696 GetRequestMethod(requestMethod);
6697
6698 profiler_add_network_marker(
6699 mURI, requestMethod, mPriority, mChannelId, NetworkLoadType::LOAD_START,
6700 mChannelCreationTimestamp, mLastStatusReported, 0, mCacheDisposition,
6701 mLoadInfo->GetInnerWindowID(),
6702 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing());
6703 }
6704
6705 // Added due to PauseTask/DelayHttpChannel
6706 if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
6707
6708 // record asyncopen time unconditionally and clear it if we
6709 // don't want it after OnModifyRequest() weighs in. But waiting for
6710 // that to complete would mean we don't include proxy resolution in the
6711 // timing.
6712 if (!LoadAsyncOpenTimeOverriden()) {
6713 mAsyncOpenTime = aTimeStamp;
6714 }
6715
6716 // Remember we have Authorization header set here. We need to check on it
6717 // just once and early, AsyncOpen is the best place.
6718 StoreCustomAuthHeader(mRequestHead.HasHeader(nsHttp::Authorization));
6719
6720 bool willCallback = false;
6721 // We are about to do an async lookup to check if the URI is a tracker. If
6722 // yes, this channel will be canceled by channel classifier. Chances are the
6723 // lookup is not needed so CheckIsTrackerWithLocalTable() will return an
6724 // error and then we can MaybeResolveProxyAndBeginConnect() right away.
6725 // We skip the check in case this is an internal redirected channel
6726 if (!LoadAuthRedirectedChannel() && NS_ShouldClassifyChannel(this)) {
6727 RefPtr<nsHttpChannel> self = this;
6728 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
6729 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
6730 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
6731 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
6732 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
6733
6734 // 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
6735 // 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
6736 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
6737
6738 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
6739 }))((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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ *((volatile int*)__null) = 6732; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
;
6740 }
6741
6742 if (!willCallback) {
6743 // We can do MaybeResolveProxyAndBeginConnect immediately if
6744 // CheckIsTrackerWithLocalTable is failed. Note that we don't need to
6745 // handle the failure because BeginConnect() will return synchronously and
6746 // the caller will be responsible for handling it.
6747 MaybeResolveProxyAndBeginConnect();
6748 }
6749}
6750
6751void nsHttpChannel::MaybeResolveProxyAndBeginConnect() {
6752 nsresult rv;
6753
6754 // The common case for HTTP channels is to begin proxy resolution and return
6755 // at this point. The only time we know mProxyInfo already is if we're
6756 // proxying a non-http protocol like ftp. We don't need to discover proxy
6757 // settings if we are never going to make a network connection.
6758 if (!mProxyInfo &&
6759 !(mLoadFlags & (LOAD_ONLY_FROM_CACHE | LOAD_NO_NETWORK_IO)) &&
6760 !BypassProxy() && NS_SUCCEEDED(ResolveProxy())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ResolveProxy())),
1)))
) {
6761 return;
6762 }
6763
6764 if (!gHttpHandler->Active()) {
6765 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
6766 ("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)
6767 "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)
6768 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
6769 rv = NS_ERROR_NOT_AVAILABLE;
6770 } else {
6771 rv = BeginConnect();
6772 }
6773 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6774 CloseCacheEntry(false);
6775 Unused << AsyncAbort(rv);
6776 }
6777}
6778
6779nsresult nsHttpChannel::AsyncOpenOnTailUnblock() {
6780 return AsyncOpen(mListener);
6781}
6782
6783already_AddRefed<nsChannelClassifier>
6784nsHttpChannel::GetOrCreateChannelClassifier() {
6785 if (!mChannelClassifier) {
6786 mChannelClassifier = new nsChannelClassifier(this);
6787 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)
6788 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)
;
6789 }
6790
6791 RefPtr<nsChannelClassifier> classifier = mChannelClassifier;
6792 return classifier.forget();
6793}
6794
6795ProxyDNSStrategy nsHttpChannel::GetProxyDNSStrategy() {
6796 // When network_dns_force_use_https_rr is true, return DNS_PREFETCH_ORIGIN.
6797 // This ensures that we always perform HTTPS RR query.
6798 nsCOMPtr<nsProxyInfo> proxyInfo(static_cast<nsProxyInfo*>(mProxyInfo.get()));
6799 if (!proxyInfo || StaticPrefs::network_dns_force_use_https_rr()) {
6800 return ProxyDNSStrategy::ORIGIN;
6801 }
6802
6803 // If the proxy is not to perform name resolution itself.
6804 return GetProxyDNSStrategyHelper(proxyInfo->Type(), proxyInfo->Flags());
6805}
6806
6807// BeginConnect() SHOULD NOT call AsyncAbort(). AsyncAbort will be called by
6808// functions that called BeginConnect if needed. Only
6809// MaybeResolveProxyAndBeginConnect and OnProxyAvailable ever call
6810// BeginConnect.
6811nsresult nsHttpChannel::BeginConnect() {
6812 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)
;
6813 nsresult rv;
6814
6815 // It is the caller's responsibility to not call us late in shutdown.
6816 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gHttpHandler->Active()"
")"); do { *((volatile int*)__null) = 6816; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6817
6818 // Construct connection info object
6819 nsAutoCString host;
6820 nsAutoCString scheme;
6821 int32_t port = -1;
6822 bool isHttps = mURI->SchemeIs("https");
6823
6824 rv = mURI->GetScheme(scheme);
6825 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiHost(host);
6826 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetPort(&port);
6827 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiSpec(mSpec);
6828 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6829 return rv;
6830 }
6831
6832 // Just a warning here because some nsIURIs do not implement this method.
6833 Unused << 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))"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6833)
;
6834
6835 // Reject the URL if it doesn't specify a host
6836 if (host.IsEmpty()) {
6837 rv = NS_ERROR_MALFORMED_URI;
6838 return rv;
6839 }
6840 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)
;
6841 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)
;
6842
6843 nsCOMPtr<nsProxyInfo> proxyInfo;
6844 if (mProxyInfo) proxyInfo = do_QueryInterface(mProxyInfo);
6845
6846 if (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) {
6847 if (!proxyInfo) {
6848 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)
;
6849 return NS_ERROR_FAILURE;
6850 }
6851
6852 if (!proxyInfo->IsHTTP() && !proxyInfo->IsHTTPS()) {
6853 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)
;
6854 return NS_ERROR_FAILURE;
6855 }
6856 }
6857
6858 mRequestHead.SetHTTPS(isHttps);
6859 mRequestHead.SetOrigin(scheme, host, port);
6860
6861 SetOriginHeader();
6862 SetDoNotTrack();
6863 SetGlobalPrivacyControl();
6864
6865 OriginAttributes originAttributes;
6866 // Regular principal in case we have a proxy.
6867 if (proxyInfo &&
6868 !StaticPrefs::privacy_partition_network_state_connection_with_proxy()) {
6869 StoragePrincipalHelper::GetOriginAttributes(
6870 this, originAttributes, StoragePrincipalHelper::eRegularPrincipal);
6871 } else {
6872 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
6873 this, originAttributes);
6874 }
6875
6876 // Adjust mCaps according to our request headers:
6877 // - If "Connection: close" is set as a request header, then do not bother
6878 // trying to establish a keep-alive connection.
6879 if (mRequestHead.HasHeaderValue(nsHttp::Connection, "close")) {
6880 mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE(1 << 0));
6881 StoreAllowHttp3(false);
6882 }
6883
6884 gHttpHandler->MaybeAddAltSvcForTesting(mURI, mUsername, mPrivateBrowsing,
6885 mCallbacks, originAttributes);
6886
6887 RefPtr<nsHttpConnectionInfo> connInfo;
6888#ifdef FUZZING
6889 if (StaticPrefs::fuzzing_necko_http3()) {
6890 connInfo =
6891 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
6892 originAttributes, host, port, true);
6893 } else {
6894#endif
6895 if (mWebTransportSessionEventListener) {
6896 connInfo =
6897 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
6898 originAttributes, isHttps, true, true);
6899 bool dedicated = true;
6900 nsresult rv;
6901 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
6902 do_QueryInterface(mWebTransportSessionEventListener, &rv);
6903 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6903); return rv; } } while (false)
;
6904 wtconSettings->GetDedicated(&dedicated);
6905 if (dedicated) {
6906 connInfo->SetWebTransportId(
6907 gHttpHandler->ConnMgr()->GenerateNewWebTransportId());
6908 }
6909 } else {
6910 connInfo = new nsHttpConnectionInfo(host, port, ""_ns, mUsername,
6911 proxyInfo, originAttributes, isHttps);
6912 }
6913#ifdef FUZZING
6914 }
6915#endif
6916
6917 bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
6918
6919 bool http3Allowed = Http3Allowed();
6920 if (!http3Allowed) {
6921 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
6922 }
6923
6924 RefPtr<AltSvcMapping> mapping;
6925 if (!mConnectionInfo && LoadAllowAltSvc() && // per channel
6926 !mWebTransportSessionEventListener && (http2Allowed || http3Allowed) &&
6927 !(mLoadFlags & LOAD_FRESH_CONNECTION) &&
6928 AltSvcMapping::AcceptableProxy(proxyInfo) &&
6929 (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
6930 (mapping = gHttpHandler->GetAltServiceMapping(
6931 scheme, host, port, mPrivateBrowsing, originAttributes, http2Allowed,
6932 http3Allowed))) {
6933 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)
6934 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)
6935 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)
;
6936
6937 if (!(mLoadFlags & LOAD_ANONYMOUS) && !mPrivateBrowsing) {
6938 nsAutoCString altUsedLine(mapping->AlternateHost());
6939 bool defaultPort =
6940 mapping->AlternatePort() ==
6941 (isHttps ? NS_HTTPS_DEFAULT_PORT443 : NS_HTTP_DEFAULT_PORT80);
6942 if (!defaultPort) {
6943 altUsedLine.AppendLiteral(":");
6944 altUsedLine.AppendInt(mapping->AlternatePort());
6945 }
6946 // Like what we did for 'Authorization' header, we need to do the same for
6947 // 'Alt-Used' for avoiding this header being shown in the ServiceWorker
6948 // FetchEvent.
6949 Unused << mRequestHead.ClearHeader(nsHttp::Alternate_Service_Used);
6950 rv = mRequestHead.SetHeader(nsHttp::Alternate_Service_Used, altUsedLine,
6951 false,
6952 nsHttpHeaderArray::eVarietyRequestDefault);
6953 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 6953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 6953; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6954 }
6955
6956 nsCOMPtr<nsIConsoleService> consoleService;
6957 consoleService = mozilla::components::Console::Service();
6958 if (consoleService && !host.Equals(mapping->AlternateHost())) {
6959 nsAutoString message(u"Alternate Service Mapping found: "_ns);
6960 AppendASCIItoUTF16(scheme, message);
6961 message.AppendLiteral(u"://");
6962 AppendASCIItoUTF16(host, message);
6963 message.AppendLiteral(u":");
6964 message.AppendInt(port);
6965 message.AppendLiteral(u" to ");
6966 AppendASCIItoUTF16(scheme, message);
6967 message.AppendLiteral(u"://");
6968 AppendASCIItoUTF16(mapping->AlternateHost(), message);
6969 message.AppendLiteral(u":");
6970 message.AppendInt(mapping->AlternatePort());
6971 consoleService->LogStringMessage(message.get());
6972 }
6973
6974 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)
;
6975 mapping->GetConnectionInfo(getter_AddRefs(mConnectionInfo), proxyInfo,
6976 originAttributes);
6977 Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_USE_ALTSVC, true);
6978 } else if (mConnectionInfo) {
6979 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)
;
6980 Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_USE_ALTSVC, false);
6981 } else {
6982 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)
;
6983
6984 mConnectionInfo = connInfo;
6985 Telemetry::Accumulate(Telemetry::HTTP_TRANSACTION_USE_ALTSVC, false);
6986 }
6987
6988 bool trrEnabled = false;
6989 auto dnsStrategy = GetProxyDNSStrategy();
6990 bool httpsRRAllowed =
6991 !LoadBeConservative() && !(mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) &&
6992 !(mLoadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
6993 mLoadInfo->GetExternalContentPolicyType() !=
6994 ExtContentPolicy::TYPE_DOCUMENT) &&
6995 dnsStrategy == ProxyDNSStrategy::ORIGIN &&
6996 !mConnectionInfo->UsingConnect() && canUseHTTPSRRonNetwork(trrEnabled) &&
6997 StaticPrefs::network_dns_use_https_rr_as_altsvc();
6998 if (!httpsRRAllowed) {
6999 DisallowHTTPSRR(mCaps);
7000 } else if (trrEnabled) {
7001 if (nsIRequest::GetTRRMode() != nsIRequest::TRR_DISABLED_MODE) {
7002 mCaps |= NS_HTTP_FORCE_WAIT_HTTP_RR(1 << 22);
7003 }
7004 }
7005 // No need to lookup HTTPSSVC record if mHTTPSSVCRecord already contains a
7006 // value.
7007 StoreUseHTTPSSVC(StaticPrefs::network_dns_upgrade_with_https_rr() &&
7008 httpsRRAllowed && mHTTPSSVCRecord.isNothing());
7009
7010 // Need to re-ask the handler, since mConnectionInfo may not be the connInfo
7011 // we used earlier
7012 if (!mConnectionInfo->IsHttp3() &&
7013 gHttpHandler->IsHttp2Excluded(mConnectionInfo)) {
7014 StoreAllowSpdy(0);
7015 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
7016 mConnectionInfo->SetNoSpdy(true);
7017 }
7018
7019 // We can be passed with the auth provider if this channel was
7020 // a result of redirect due to auth retry
7021 if (!mAuthProvider) {
7022 mAuthProvider = new nsHttpChannelAuthProvider();
7023 }
7024
7025 rv = mAuthProvider->Init(this);
7026 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7027 return rv;
7028 }
7029
7030 // check to see if authorization headers should be included
7031 // CustomAuthHeader is set in AsyncOpen if we find Authorization header
7032 rv = mAuthProvider->AddAuthorizationHeaders(LoadCustomAuthHeader());
7033 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7034 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)
7035 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)
;
7036 }
7037
7038 // If TimingEnabled flag is not set after OnModifyRequest() then
7039 // clear the already recorded AsyncOpen value for consistency.
7040 if (!LoadTimingEnabled()) mAsyncOpenTime = TimeStamp();
7041
7042 // if this somehow fails we can go on without it
7043 Unused << gHttpHandler->AddConnectionHeader(&mRequestHead, mCaps);
7044
7045 if (!LoadIsTRRServiceChannel() &&
7046 ((mLoadFlags & LOAD_FRESH_CONNECTION) ||
7047 (!StaticPrefs::network_dns_only_refresh_on_fresh_connection() &&
7048 (mLoadFlags & VALIDATE_ALWAYS ||
7049 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
)))) {
7050 mCaps |= NS_HTTP_REFRESH_DNS(1 << 3);
7051 }
7052
7053 if (gHttpHandler->CriticalRequestPrioritization()) {
7054 if (mClassOfService.Flags() & nsIClassOfService::Leader) {
7055 mCaps |= NS_HTTP_LOAD_AS_BLOCKING(1 << 6);
7056 }
7057 if (mClassOfService.Flags() & nsIClassOfService::Unblocked) {
7058 mCaps |= NS_HTTP_LOAD_UNBLOCKED(1 << 8);
7059 }
7060 if (mClassOfService.Flags() & nsIClassOfService::UrgentStart &&
7061 gHttpHandler->IsUrgentStartEnabled()) {
7062 mCaps |= NS_HTTP_URGENT_START(1 << 12);
7063 SetPriority(nsISupportsPriority::PRIORITY_HIGHEST);
7064 }
7065 }
7066
7067 // Force-Reload should reset the persistent connection pool for this host
7068 if (mLoadFlags & LOAD_FRESH_CONNECTION) {
7069 // just the initial document resets the whole pool
7070 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
7071 gHttpHandler->AltServiceCache()->ClearAltServiceMappings();
7072 rv = gHttpHandler->DoShiftReloadConnectionCleanupWithConnInfo(
7073 mConnectionInfo);
7074 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7075 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
7076 "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)
7077 "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)
7078 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)
;
7079 }
7080 }
7081 }
7082
7083 // We may have been cancelled already, either by on-modify-request
7084 // listeners or load group observers; in that case, we should not send the
7085 // request to the server
7086 if (mCanceled) {
7087 return mStatus;
7088 }
7089 // skip classifier checks if this channel was the result of internal auth
7090 // redirect
7091 bool shouldBeClassified =
7092 !LoadAuthRedirectedChannel() && NS_ShouldClassifyChannel(this);
7093
7094 if (shouldBeClassified) {
7095 if (LoadChannelClassifierCancellationPending()) {
7096 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
7097 ("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)
7098 "[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)
7099 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
7100 return NS_OK;
7101 }
7102
7103 ReEvaluateReferrerAfterTrackingStatusIsKnown();
7104 }
7105
7106 MaybeStartDNSPrefetch();
7107
7108 rv = CallOrWaitForResume(
7109 [](nsHttpChannel* self) { return self->PrepareToConnect(); });
7110 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7111 return rv;
7112 }
7113
7114 if (shouldBeClassified) {
7115 // Start nsChannelClassifier to catch phishing and malware URIs.
7116 RefPtr<nsChannelClassifier> channelClassifier =
7117 GetOrCreateChannelClassifier();
7118 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)
7119 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)
;
7120 channelClassifier->Start();
7121 }
7122
7123 return NS_OK;
7124}
7125
7126void nsHttpChannel::MaybeStartDNSPrefetch() {
7127 // Start a DNS lookup very early in case the real open is queued the DNS can
7128 // happen in parallel. Do not do so in the presence of an HTTP proxy as
7129 // all lookups other than for the proxy itself are done by the proxy.
7130 // Also we don't do a lookup if the LOAD_NO_NETWORK_IO or
7131 // LOAD_ONLY_FROM_CACHE flags are set.
7132 //
7133 // We keep the DNS prefetch object around so that we can retrieve
7134 // timing information from it. There is no guarantee that we actually
7135 // use the DNS prefetch data for the real connection, but as we keep
7136 // this data around for 3 minutes by default, this should almost always
7137 // be correct, and even when it isn't, the timing still represents _a_
7138 // valid DNS lookup timing for the site, even if it is not _the_
7139 // timing we used.
7140 if ((mLoadFlags & (LOAD_NO_NETWORK_IO | LOAD_ONLY_FROM_CACHE)) ||
7141 LoadAuthRedirectedChannel()) {
7142 return;
7143 }
7144
7145 auto dnsStrategy = GetProxyDNSStrategy();
7146
7147 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
7148 ("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)
7149 "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)
7150 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)
7151 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)
;
7152
7153 if (dnsStrategy == ProxyDNSStrategy::ORIGIN) {
7154 OriginAttributes originAttributes;
7155 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
7156 this, originAttributes);
7157
7158 mDNSPrefetch =
7159 new nsDNSPrefetch(mURI, originAttributes, nsIRequest::GetTRRMode(),
7160 this, LoadTimingEnabled());
7161 nsIDNSService::DNSFlags dnsFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS;
7162 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
7163 dnsFlags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
7164 }
7165
7166 Unused << mDNSPrefetch->PrefetchHigh(dnsFlags);
7167
7168 bool unused;
7169 if (StaticPrefs::network_dns_use_https_rr_as_altsvc() && !mHTTPSSVCRecord &&
7170 !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) &&
7171 canUseHTTPSRRonNetwork(unused)) {
7172 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mHTTPSSVCRecord"
")"); do { *((volatile int*)__null) = 7172; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7173
7174 OriginAttributes originAttributes;
7175 StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(this,
7176 originAttributes);
7177
7178 RefPtr<nsDNSPrefetch> resolver =
7179 new nsDNSPrefetch(mURI, originAttributes, nsIRequest::GetTRRMode());
7180 Unused << resolver->FetchHTTPSSVC(mCaps & NS_HTTP_REFRESH_DNS(1 << 3), true,
7181 [](nsIDNSHTTPSSVCRecord*) {
7182 // Do nothing. This is a DNS prefetch.
7183 });
7184 }
7185 }
7186}
7187
7188NS_IMETHODIMPnsresult
7189nsHttpChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) {
7190 if (mCacheEntry && !LoadCacheEntryIsWriteOnly()) {
7191 int64_t dataSize = 0;
7192 mCacheEntry->GetDataSize(&dataSize);
7193 *aEncodedBodySize = dataSize;
7194 } else {
7195 *aEncodedBodySize = mLogicalOffset;
7196 }
7197 return NS_OK;
7198}
7199
7200//-----------------------------------------------------------------------------
7201// nsHttpChannel::nsIHttpChannelInternal
7202//-----------------------------------------------------------------------------
7203
7204NS_IMETHODIMPnsresult
7205nsHttpChannel::GetIsAuthChannel(bool* aIsAuthChannel) {
7206 *aIsAuthChannel = mIsAuthChannel;
7207 return NS_OK;
7208}
7209
7210NS_IMETHODIMPnsresult
7211nsHttpChannel::SetChannelIsForDownload(bool aChannelIsForDownload) {
7212 if (aChannelIsForDownload) {
7213 AddClassFlags(nsIClassOfService::Throttleable);
7214 } else {
7215 ClearClassFlags(nsIClassOfService::Throttleable);
7216 }
7217
7218 return HttpBaseChannel::SetChannelIsForDownload(aChannelIsForDownload);
7219}
7220
7221base::ProcessId nsHttpChannel::ProcessId() {
7222 nsCOMPtr<nsIParentChannel> parentChannel;
7223 NS_QueryNotificationCallbacks(this, parentChannel);
7224 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
7225 return httpParent->OtherPid();
7226 }
7227 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
7228 return docParent->OtherPid();
7229 }
7230 return base::GetCurrentProcId();
7231}
7232
7233auto nsHttpChannel::AttachStreamFilter() -> RefPtr<ChildEndpointPromise> {
7234 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)
;
7235 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7235); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { *((volatile int*)__null) = 7235; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7236
7237 if (!ProcessId()) {
7238 return ChildEndpointPromise::CreateAndReject(false, __func__);
7239 }
7240
7241 nsCOMPtr<nsIParentChannel> parentChannel;
7242 NS_QueryNotificationCallbacks(this, parentChannel);
7243
7244 // If our listener is a DocumentLoadListener, then we might handle
7245 // multi-part responses here in the parent process. The current extension
7246 // API doesn't understand the parsed multipart format, so we defer responding
7247 // here until CallOnStartRequest, and attach the StreamFilter before the
7248 // multipart handler (in the parent process!) if applicable.
7249 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
7250 StreamFilterRequest* request = mStreamFilterRequests.AppendElement();
7251 request->mPromise = new ChildEndpointPromise::Private(__func__);
7252 return request->mPromise;
7253 }
7254
7255 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
7256 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
7257 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
7258 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7259 return ChildEndpointPromise::CreateAndReject(false, __func__);
7260 }
7261
7262 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
7263 return httpParent->AttachStreamFilter(std::move(parent), std::move(child));
7264 }
7265
7266 extensions::StreamFilterParent::Attach(this, std::move(parent));
7267 return ChildEndpointPromise::CreateAndResolve(std::move(child), __func__);
7268}
7269
7270NS_IMETHODIMPnsresult
7271nsHttpChannel::GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) {
7272 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)
;
7273 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimeStamp"
")"); do { *((volatile int*)__null) = 7273; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7274 *aTimeStamp = mNavigationStartTimeStamp;
7275 return NS_OK;
7276}
7277
7278NS_IMETHODIMPnsresult
7279nsHttpChannel::SetNavigationStartTimeStamp(TimeStamp aTimeStamp) {
7280 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)
;
7281 mNavigationStartTimeStamp = aTimeStamp;
7282 return NS_OK;
7283}
7284
7285//-----------------------------------------------------------------------------
7286// nsHttpChannel::nsISupportsPriority
7287//-----------------------------------------------------------------------------
7288
7289NS_IMETHODIMPnsresult
7290nsHttpChannel::SetPriority(int32_t value) {
7291 int16_t newValue = clamped<int32_t>(value, INT16_MIN(-32767-1), INT16_MAX(32767));
7292 if (mPriority == newValue) return NS_OK;
7293
7294 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)
;
7295
7296 mPriority = newValue;
7297 if (mTransaction) {
7298 nsresult rv = gHttpHandler->RescheduleTransaction(mTransaction, mPriority);
7299 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7300 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
7301 ("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)
7302 "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)
7303 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)
;
7304 }
7305 }
7306
7307 // If this channel is the real channel for an e10s channel, notify the
7308 // child side about the priority change as well.
7309 nsCOMPtr<nsIParentChannel> parentChannel;
7310 NS_QueryNotificationCallbacks(this, parentChannel);
7311 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
7312 if (httpParent) {
7313 httpParent->DoSendSetPriority(newValue);
7314 }
7315
7316 return NS_OK;
7317}
7318
7319//-----------------------------------------------------------------------------
7320// HttpChannel::nsIClassOfService
7321//-----------------------------------------------------------------------------
7322
7323void nsHttpChannel::OnClassOfServiceUpdated() {
7324 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)
7325 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)
;
7326
7327 if (mTransaction) {
7328 gHttpHandler->UpdateClassOfServiceOnTransaction(mTransaction,
7329 mClassOfService);
7330 }
7331 if (EligibleForTailing()) {
7332 RemoveAsNonTailRequest();
7333 } else {
7334 AddAsNonTailRequest();
7335 }
7336}
7337
7338NS_IMETHODIMPnsresult
7339nsHttpChannel::SetClassFlags(uint32_t inFlags) {
7340 uint32_t previous = mClassOfService.Flags();
7341 mClassOfService.SetFlags(inFlags);
7342 if (previous != mClassOfService.Flags()) {
7343 OnClassOfServiceUpdated();
7344 }
7345 return NS_OK;
7346}
7347
7348NS_IMETHODIMPnsresult
7349nsHttpChannel::AddClassFlags(uint32_t inFlags) {
7350 uint32_t previous = mClassOfService.Flags();
7351 mClassOfService.SetFlags(inFlags | mClassOfService.Flags());
7352 if (previous != mClassOfService.Flags()) {
7353 OnClassOfServiceUpdated();
7354 }
7355 return NS_OK;
7356}
7357
7358NS_IMETHODIMPnsresult
7359nsHttpChannel::ClearClassFlags(uint32_t inFlags) {
7360 uint32_t previous = mClassOfService.Flags();
7361 mClassOfService.SetFlags(~inFlags & mClassOfService.Flags());
7362 if (previous != mClassOfService.Flags()) {
7363 OnClassOfServiceUpdated();
7364 }
7365 return NS_OK;
7366}
7367
7368NS_IMETHODIMPnsresult
7369nsHttpChannel::SetClassOfService(ClassOfService cos) {
7370 ClassOfService previous = mClassOfService;
7371 mClassOfService = cos;
7372 if (previous != mClassOfService) {
7373 OnClassOfServiceUpdated();
7374 }
7375 return NS_OK;
7376}
7377
7378NS_IMETHODIMPnsresult
7379nsHttpChannel::SetIncremental(bool incremental) {
7380 bool previous = mClassOfService.Incremental();
7381 mClassOfService.SetIncremental(incremental);
7382 if (previous != mClassOfService.Incremental()) {
7383 OnClassOfServiceUpdated();
7384 }
7385 return NS_OK;
7386}
7387
7388//-----------------------------------------------------------------------------
7389// nsHttpChannel::nsIProtocolProxyCallback
7390//-----------------------------------------------------------------------------
7391
7392NS_IMETHODIMPnsresult
7393nsHttpChannel::OnProxyAvailable(nsICancelable* request, nsIChannel* channel,
7394 nsIProxyInfo* pi, nsresult status) {
7395 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)
7396 " 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)
7397 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)
7398 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)
;
7399 mProxyRequest = nullptr;
7400
7401 nsresult rv;
7402
7403 // If status is a failure code, then it means that we failed to resolve
7404 // proxy info. That is a non-fatal error assuming it wasn't because the
7405 // request was canceled. We just failover to DIRECT when proxy resolution
7406 // fails (failure can mean that the PAC URL could not be loaded).
7407
7408 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
7409 mProxyInfo = pi;
7410
7411 if (mProxyInfo) {
7412 nsAutoCStringN<8> type;
7413 mProxyInfo->GetType(type);
7414 uint32_t flags = 0;
7415 mProxyInfo->GetFlags(&flags);
7416
7417 if (type.EqualsLiteral("socks")) {
7418 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
7419 glean::networking::proxy_info_type
7420 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5h)
7421 .Add(1);
7422 } else {
7423 glean::networking::proxy_info_type
7424 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5)
7425 .Add(1);
7426 }
7427 } else if (type.EqualsLiteral("socks4")) {
7428 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
7429 glean::networking::proxy_info_type
7430 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4a)
7431 .Add(1);
7432 } else {
7433 glean::networking::proxy_info_type
7434 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4)
7435 .Add(1);
7436 }
7437 } else if (type.EqualsLiteral("http")) {
7438 glean::networking::proxy_info_type
7439 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttp)
7440 .Add(1);
7441 } else if (type.EqualsLiteral("https")) {
7442 glean::networking::proxy_info_type
7443 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttps)
7444 .Add(1);
7445 } else if (type.EqualsLiteral("direct")) {
7446 glean::networking::proxy_info_type
7447 .EnumGet(glean::networking::ProxyInfoTypeLabel::eDirect)
7448 .Add(1);
7449 } else {
7450 glean::networking::proxy_info_type
7451 .EnumGet(glean::networking::ProxyInfoTypeLabel::eUnknown)
7452 .Add(1);
7453 }
7454 }
7455 }
7456
7457 if (!gHttpHandler->Active()) {
7458 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
7459 ("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)
7460 "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)
7461 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
7462 rv = NS_ERROR_NOT_AVAILABLE;
7463 } else {
7464 rv = BeginConnect();
7465 }
7466
7467 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7468 CloseCacheEntry(false);
7469 Unused << AsyncAbort(rv);
7470 }
7471 return rv;
7472}
7473
7474//-----------------------------------------------------------------------------
7475// nsHttpChannel::nsIProxiedChannel
7476//-----------------------------------------------------------------------------
7477
7478NS_IMETHODIMPnsresult
7479nsHttpChannel::GetProxyInfo(nsIProxyInfo** result) {
7480 if (!mConnectionInfo) {
7481 *result = do_AddRef(mProxyInfo).take();
7482 } else {
7483 *result = do_AddRef(mConnectionInfo->ProxyInfo()).take();
7484 }
7485 return NS_OK;
7486}
7487
7488//-----------------------------------------------------------------------------
7489// nsHttpChannel::nsITimedChannel
7490//-----------------------------------------------------------------------------
7491
7492NS_IMETHODIMPnsresult
7493nsHttpChannel::GetDomainLookupStart(TimeStamp* _retval) {
7494 if (mTransaction) {
7495 *_retval = mTransaction->GetDomainLookupStart();
7496 } else {
7497 *_retval = mTransactionTimings.domainLookupStart;
7498 }
7499 return NS_OK;
7500}
7501
7502NS_IMETHODIMPnsresult
7503nsHttpChannel::GetDomainLookupEnd(TimeStamp* _retval) {
7504 if (mTransaction) {
7505 *_retval = mTransaction->GetDomainLookupEnd();
7506 } else {
7507 *_retval = mTransactionTimings.domainLookupEnd;
7508 }
7509 return NS_OK;
7510}
7511
7512NS_IMETHODIMPnsresult
7513nsHttpChannel::GetConnectStart(TimeStamp* _retval) {
7514 if (mTransaction) {
7515 *_retval = mTransaction->GetConnectStart();
7516 } else {
7517 *_retval = mTransactionTimings.connectStart;
7518 }
7519 return NS_OK;
7520}
7521
7522NS_IMETHODIMPnsresult
7523nsHttpChannel::GetTcpConnectEnd(TimeStamp* _retval) {
7524 if (mTransaction) {
7525 *_retval = mTransaction->GetTcpConnectEnd();
7526 } else {
7527 *_retval = mTransactionTimings.tcpConnectEnd;
7528 }
7529 return NS_OK;
7530}
7531
7532NS_IMETHODIMPnsresult
7533nsHttpChannel::GetSecureConnectionStart(TimeStamp* _retval) {
7534 if (mTransaction) {
7535 *_retval = mTransaction->GetSecureConnectionStart();
7536 } else {
7537 *_retval = mTransactionTimings.secureConnectionStart;
7538 }
7539 return NS_OK;
7540}
7541
7542NS_IMETHODIMPnsresult
7543nsHttpChannel::GetConnectEnd(TimeStamp* _retval) {
7544 if (mTransaction) {
7545 *_retval = mTransaction->GetConnectEnd();
7546 } else {
7547 *_retval = mTransactionTimings.connectEnd;
7548 }
7549 return NS_OK;
7550}
7551
7552NS_IMETHODIMPnsresult
7553nsHttpChannel::GetRequestStart(TimeStamp* _retval) {
7554 if (mTransaction) {
7555 *_retval = mTransaction->GetRequestStart();
7556 } else {
7557 *_retval = mTransactionTimings.requestStart;
7558 }
7559 return NS_OK;
7560}
7561
7562NS_IMETHODIMPnsresult
7563nsHttpChannel::GetResponseStart(TimeStamp* _retval) {
7564 if (mTransaction) {
7565 *_retval = mTransaction->GetResponseStart();
7566 } else {
7567 *_retval = mTransactionTimings.responseStart;
7568 }
7569 return NS_OK;
7570}
7571
7572NS_IMETHODIMPnsresult
7573nsHttpChannel::GetResponseEnd(TimeStamp* _retval) {
7574 if (mTransaction) {
7575 *_retval = mTransaction->GetResponseEnd();
7576 } else {
7577 *_retval = mTransactionTimings.responseEnd;
7578 }
7579 return NS_OK;
7580}
7581
7582NS_IMETHODIMPnsresult
7583nsHttpChannel::GetTransactionPending(TimeStamp* _retval) {
7584 if (mTransaction) {
7585 *_retval = mTransaction->GetPendingTime();
7586 } else {
7587 *_retval = mTransactionTimings.transactionPending;
7588 }
7589 return NS_OK;
7590}
7591
7592//-----------------------------------------------------------------------------
7593// nsHttpChannel::nsIHttpAuthenticableChannel
7594//-----------------------------------------------------------------------------
7595
7596NS_IMETHODIMPnsresult
7597nsHttpChannel::GetIsSSL(bool* aIsSSL) {
7598 // this attribute is really misnamed - it wants to know if
7599 // https:// is being used. SSL might be used to cover http://
7600 // in some circumstances (proxies, http/2, etc..)
7601 return mURI->SchemeIs("https", aIsSSL);
7602}
7603
7604NS_IMETHODIMPnsresult
7605nsHttpChannel::GetProxyMethodIsConnect(bool* aProxyMethodIsConnect) {
7606 *aProxyMethodIsConnect = mConnectionInfo->UsingConnect();
7607 return NS_OK;
7608}
7609
7610NS_IMETHODIMPnsresult
7611nsHttpChannel::GetServerResponseHeader(nsACString& value) {
7612 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
7613 return mResponseHead->GetHeader(nsHttp::Server, value);
7614}
7615
7616NS_IMETHODIMPnsresult
7617nsHttpChannel::GetProxyChallenges(nsACString& value) {
7618 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
7619 return mResponseHead->GetHeader(nsHttp::Proxy_Authenticate, value);
7620}
7621
7622NS_IMETHODIMPnsresult
7623nsHttpChannel::GetWWWChallenges(nsACString& value) {
7624 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
7625 return mResponseHead->GetHeader(nsHttp::WWW_Authenticate, value);
7626}
7627
7628NS_IMETHODIMPnsresult
7629nsHttpChannel::SetProxyCredentials(const nsACString& value) {
7630 return mRequestHead.SetHeader(nsHttp::Proxy_Authorization, value);
7631}
7632
7633NS_IMETHODIMPnsresult
7634nsHttpChannel::SetWWWCredentials(const nsACString& value) {
7635 // This method is called when various browser initiated authorization
7636 // code sets the credentials. We need to flag this header as the
7637 // "browser default" so it does not show up in the ServiceWorker
7638 // FetchEvent. This may actually get called more than once, though,
7639 // so we clear the header first since "default" headers are not
7640 // allowed to overwrite normally.
7641 Unused << mRequestHead.ClearHeader(nsHttp::Authorization);
7642 return mRequestHead.SetHeader(nsHttp::Authorization, value, false,
7643 nsHttpHeaderArray::eVarietyRequestDefault);
7644}
7645
7646//-----------------------------------------------------------------------------
7647// Methods that nsIHttpAuthenticableChannel dupes from other IDLs, which we
7648// get from HttpBaseChannel, must be explicitly forwarded, because C++ sucks.
7649//-----------------------------------------------------------------------------
7650
7651NS_IMETHODIMPnsresult
7652nsHttpChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
7653 return HttpBaseChannel::GetLoadFlags(aLoadFlags);
7654}
7655
7656NS_IMETHODIMPnsresult
7657nsHttpChannel::GetURI(nsIURI** aURI) { return HttpBaseChannel::GetURI(aURI); }
7658
7659NS_IMETHODIMPnsresult
7660nsHttpChannel::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks) {
7661 return HttpBaseChannel::GetNotificationCallbacks(aCallbacks);
7662}
7663
7664NS_IMETHODIMPnsresult
7665nsHttpChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
7666 return HttpBaseChannel::GetLoadGroup(aLoadGroup);
7667}
7668
7669NS_IMETHODIMPnsresult
7670nsHttpChannel::GetRequestMethod(nsACString& aMethod) {
7671 return HttpBaseChannel::GetRequestMethod(aMethod);
7672}
7673
7674//-----------------------------------------------------------------------------
7675// nsHttpChannel::nsIRequestObserver
7676//-----------------------------------------------------------------------------
7677
7678void nsHttpChannel::RecordOnStartTelemetry(nsresult aStatus,
7679 bool aIsNavigation) {
7680 Telemetry::Accumulate(Telemetry::HTTP_CHANNEL_ONSTART_SUCCESS,
7681 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))));
7682
7683 mozilla::glean::networking::http_channel_onstart_status
7684 .Get(NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) ? "successful"_ns : "fail"_ns)
7685 .Add(1);
7686
7687 if (mTransaction) {
7688 Telemetry::Accumulate(
7689 Telemetry::HTTP3_CHANNEL_ONSTART_SUCCESS,
7690 (mTransaction->IsHttp3Used()) ? "http3"_ns : "no_http3"_ns,
7691 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))));
7692 }
7693
7694 enum class HttpOnStartState : uint32_t {
7695 Success = 0,
7696 DNSError = 1,
7697 Others = 2,
7698 };
7699
7700 if (TRRService::Get() && TRRService::Get()->IsConfirmed()) {
7701 // Note this telemetry probe is not working when DNS resolution is done in
7702 // the socket process.
7703 HttpOnStartState state = HttpOnStartState::Others;
7704 if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
7705 state = HttpOnStartState::Success;
7706 } else if (aStatus == NS_ERROR_UNKNOWN_HOST ||
7707 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST) {
7708 state = HttpOnStartState::DNSError;
7709 }
7710
7711 if (aIsNavigation) {
7712 Telemetry::Accumulate(Telemetry::HTTP_CHANNEL_PAGE_ONSTART_SUCCESS_TRR3,
7713 TRRService::ProviderKey(),
7714 static_cast<uint32_t>(state));
7715 } else {
7716 Telemetry::Accumulate(Telemetry::HTTP_CHANNEL_SUB_ONSTART_SUCCESS_TRR3,
7717 TRRService::ProviderKey(),
7718 static_cast<uint32_t>(state));
7719 }
7720 }
7721
7722 if (nsIOService::UseSocketProcess() && mTransaction) {
7723 const TimeStamp now = TimeStamp::Now();
7724 TimeStamp responseEnd = mTransaction->GetResponseEnd();
7725 if (!responseEnd.IsNull()) {
7726 PerfStats::RecordMeasurement(PerfStats::Metric::ResponseEndSocketToParent,
7727 now - responseEnd);
7728 }
7729
7730 mOnStartRequestStartTime = mTransaction->GetOnStartRequestStartTime();
7731 if (!mOnStartRequestStartTime.IsNull()) {
7732 PerfStats::RecordMeasurement(
7733 PerfStats::Metric::OnStartRequestSocketToParent,
7734 now - mOnStartRequestStartTime);
7735 }
7736 } else {
7737 mOnStartRequestStartTime = TimeStamp::Now();
7738 }
7739}
7740
7741NS_IMETHODIMPnsresult
7742nsHttpChannel::OnStartRequest(nsIRequest* request) {
7743 nsresult rv;
7744
7745 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()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequestObserversCalled()"
")"); do { *((volatile int*)__null) = 7745; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7746
7747 AUTO_PROFILER_LABEL("nsHttpChannel::OnStartRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject7747( "nsHttpChannel::OnStartRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
7748
7749 if (!(mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) &&
7750 !WRONG_RACING_RESPONSE_SOURCE(request)(mRaceCacheWithNetwork && (((mFirstResponseSource == RESPONSE_FROM_CACHE
) && ((request) != mCachePump)) || ((mFirstResponseSource
== RESPONSE_FROM_NETWORK) && ((request) != mTransactionPump
))))
) {
7751 // capture the request's status, so our consumers will know ASAP of any
7752 // connection failures, etc - bug 93581
7753 nsresult status;
7754 request->GetStatus(&status);
7755 mStatus = status;
7756 }
7757
7758 if (mStatus == NS_ERROR_NON_LOCAL_CONNECTION_REFUSED) {
7759 MOZ_CRASH_UNSAFE(nsPrintfCString("Attempting to connect to non-local "MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7766, nsPrintfCString("Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get()) .get())
7760 "address! opener is [%s], uri is "MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7766, nsPrintfCString("Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get()) .get())
7761 "[%s]",MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7766, nsPrintfCString("Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get()) .get())
7762 mOpenerCallingScriptLocationMOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7766, nsPrintfCString("Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get()) .get())
7763 ? mOpenerCallingScriptLocation->get()MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7766, nsPrintfCString("Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get()) .get())
7764 : "unknown",MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7766, nsPrintfCString("Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get()) .get())
7765 mURI->GetSpecOrDefault().get())MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7766, nsPrintfCString("Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get()) .get())
7766 .get())MOZ_Crash("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7766, nsPrintfCString("Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get()) .get())
;
7767 }
7768
7769 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)
7770 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
7771 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)
;
7772
7773 RecordOnStartTelemetry(mStatus, IsNavigation());
7774
7775 if (mRaceCacheWithNetwork) {
7776 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " racingNetAndCache - mFirstResponseSource:%d fromCache:%d "
"fromNet:%d\n", static_cast<int32_t>(mFirstResponseSource
), request == mCachePump, request == mTransactionPump); } } while
(0)
7777 (" racingNetAndCache - mFirstResponseSource:%d fromCache:%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
, " racingNetAndCache - mFirstResponseSource:%d fromCache:%d "
"fromNet:%d\n", static_cast<int32_t>(mFirstResponseSource
), request == mCachePump, request == mTransactionPump); } } while
(0)
7778 "fromNet:%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
, " racingNetAndCache - mFirstResponseSource:%d fromCache:%d "
"fromNet:%d\n", static_cast<int32_t>(mFirstResponseSource
), request == mCachePump, request == mTransactionPump); } } while
(0)
7779 static_cast<int32_t>(mFirstResponseSource), request == mCachePump,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " racingNetAndCache - mFirstResponseSource:%d fromCache:%d "
"fromNet:%d\n", static_cast<int32_t>(mFirstResponseSource
), request == mCachePump, request == mTransactionPump); } } while
(0)
7780 request == mTransactionPump))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " racingNetAndCache - mFirstResponseSource:%d fromCache:%d "
"fromNet:%d\n", static_cast<int32_t>(mFirstResponseSource
), request == mCachePump, request == mTransactionPump); } } while
(0)
;
7781 if (mFirstResponseSource == RESPONSE_PENDING) {
7782 // When the cache wins mFirstResponseSource is set to
7783 // RESPONSE_FROM_CACHE earlier in ReadFromCache, so this must be a
7784 // response from the network.
7785 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mTransactionPump"
")"); do { *((volatile int*)__null) = 7785; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7786 LOG((" First response from network\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " First response from network\n"); } } while (0)
;
7787 {
7788 // Race condition with OnCacheEntryCheck, which is not limited
7789 // to main thread.
7790 mozilla::MutexAutoLock lock(mRCWNLock);
7791 mFirstResponseSource = RESPONSE_FROM_NETWORK;
7792 mOnStartRequestTimestamp = TimeStamp::Now();
7793
7794 // Conditional or byte range header could be added in
7795 // OnCacheEntryCheck. We need to remove them because the
7796 // request might be sent again due to auth retry and we must
7797 // not send these headers without having the entry.
7798 if (mDidReval) {
7799 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)
;
7800 UntieValidationRequest();
7801 mDidReval = false;
7802 }
7803 if (LoadCachedContentIsPartial()) {
7804 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)
;
7805 UntieByteRangeRequest();
7806 StoreCachedContentIsPartial(false);
7807 }
7808 }
7809 mAvailableCachedAltDataType.Truncate();
7810 StoreDeliveringAltData(false);
7811 } else if (WRONG_RACING_RESPONSE_SOURCE(request)(mRaceCacheWithNetwork && (((mFirstResponseSource == RESPONSE_FROM_CACHE
) && ((request) != mCachePump)) || ((mFirstResponseSource
== RESPONSE_FROM_NETWORK) && ((request) != mTransactionPump
))))
) {
7812 LOG((" Early return when racing. This response not needed."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Early return when racing. This response not needed."); }
} while (0)
;
7813 return NS_OK;
7814 }
7815 }
7816
7817 // Make sure things are what we expect them to be...
7818 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { *((volatile int*)__null
) = 7819; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
7819 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { *((volatile int*)__null
) = 7819; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
7820
7821 MOZ_ASSERT(mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")"); do { *((volatile int*)__null) = 7825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7822 LoadCachedContentIsPartial() || LoadTransactionReplaced(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")"); do { *((volatile int*)__null) = 7825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7823 "If we have both pumps, we're racing cache with network, the cache"do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")"); do { *((volatile int*)__null) = 7825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7824 " content is partial, or the cache entry was revalidated and "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")"); do { *((volatile int*)__null) = 7825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7825 "OnStopRequest was not called yet for the transaction pump.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRaceCacheWithNetwork || !(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRaceCacheWithNetwork || !(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, we're racing cache with network, the cache"
" content is partial, or the cache entry was revalidated and "
"OnStopRequest was not called yet for the transaction pump."
")"); do { *((volatile int*)__null) = 7825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7826
7827 StoreAfterOnStartRequestBegun(true);
7828 if (mOnStartRequestTimestamp.IsNull()) {
7829 mOnStartRequestTimestamp = TimeStamp::Now();
7830 }
7831
7832 mozilla::glean::networking::http_onstart_suspend_total_time
7833 .AccumulateRawDuration(mSuspendTotalTime);
7834
7835 if (mTransaction) {
7836 mProxyConnectResponseCode = mTransaction->GetProxyConnectResponseCode();
7837 if (request == mTransactionPump) {
7838 StoreDataSentToChildProcess(mTransaction->DataSentToChildProcess());
7839 }
7840
7841 if (!mSecurityInfo && !mCachePump) {
7842 // grab the security info from the connection object; the transaction
7843 // is guaranteed to own a reference to the connection.
7844 mSecurityInfo = mTransaction->SecurityInfo();
7845 }
7846
7847 uint32_t stage = mTransaction->HTTPSSVCReceivedStage();
7848 if (!LoadHTTPSSVCTelemetryReported() && stage != HTTPSSVC_NOT_USED) {
7849 Telemetry::Accumulate(Telemetry::DNS_HTTPSSVC_RECORD_RECEIVING_STAGE,
7850 stage);
7851 }
7852
7853 if (HTTPS_RR_IS_USED(stage)(stage > HTTPSSVC_NOT_PRESENT && stage < HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_2
)
) {
7854 nsAutoCString suffix(LoadEchConfigUsed() ? "_ech_used" : "");
7855 // Determine the result string based on the status.
7856 nsAutoCString result(NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) ? "success" : "failure");
7857 result.Append(suffix);
7858
7859 mozilla::glean::networking::http_channel_onstart_success_https_rr
7860 .Get(result)
7861 .Add(1);
7862 StoreHasHTTPSRR(true);
7863 }
7864
7865 StoreLoadedBySocketProcess(mTransaction->AsHttpTransactionParent() !=
7866 nullptr);
7867
7868 bool isTrr;
7869 bool echConfigUsed;
7870 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
7871 mEffectiveTRRMode, mTRRSkipReason,
7872 echConfigUsed);
7873 StoreResolvedByTRR(isTrr);
7874 StoreEchConfigUsed(echConfigUsed);
7875 }
7876
7877 // don't enter this block if we're reading from the cache...
7878 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mCachePump && mTransaction) {
7879 // mTransactionPump doesn't hit OnInputStreamReady and call this until
7880 // all of the response headers have been acquired, so we can take
7881 // ownership of them from the transaction.
7882 mResponseHead = mTransaction->TakeResponseHead();
7883 mSupportsHTTP3 = mTransaction->GetSupportsHTTP3();
7884 // the response head may be null if the transaction was cancelled. in
7885 // which case we just need to call OnStartRequest/OnStopRequest.
7886 if (mResponseHead) return ProcessResponse();
7887
7888 NS_WARNING("No response head in OnStartRequest")NS_DebugBreak(NS_DEBUG_WARNING, "No response head in OnStartRequest"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7888)
;
7889 }
7890
7891 // cache file could be deleted on our behalf, it could contain errors or
7892 // it failed to allocate memory, reload from network here.
7893 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)
) {
7894 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)
;
7895 mCacheEntry->AsyncDoom(nullptr);
7896 rv =
7897 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
7898 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) return NS_OK;
7899 }
7900
7901 // avoid crashing if mListener happens to be null...
7902 if (!mListener) {
7903 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "mListener is null" ")"); do { *(
(volatile int*)__null) = 7903; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
7904 return NS_OK;
7905 }
7906
7907 rv = ProcessCrossOriginSecurityHeaders();
7908 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7909 mStatus = rv;
7910 HandleAsyncAbort();
7911 return rv;
7912 }
7913
7914 // No process change is needed, so continue on to ContinueOnStartRequest1.
7915 return ContinueOnStartRequest1(rv);
7916}
7917
7918nsresult nsHttpChannel::ContinueOnStartRequest1(nsresult result) {
7919 nsresult rv;
7920
7921 // if process selection failed, cancel this load.
7922 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
7923 Cancel(result);
7924 return CallOnStartRequest();
7925 }
7926
7927 // before we start any content load, check for redirectTo being called
7928 // this code is executed mainly before we start load from the cache
7929 if (mAPIRedirectToURI && !mCanceled) {
7930 nsAutoCString redirectToSpec;
7931 mAPIRedirectToURI->GetAsciiSpec(redirectToSpec);
7932 LOG((" redirectTo called with uri=%s", redirectToSpec.BeginReading()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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.BeginReading
()); } } while (0)
;
7933
7934 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 7934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { *((volatile int*)__null) = 7934; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7935
7936 nsCOMPtr<nsIURI> redirectTo;
7937 mAPIRedirectToURI.swap(redirectTo);
7938
7939 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
7940 rv = StartRedirectChannelToURI(redirectTo,
7941 nsIChannelEventSink::REDIRECT_TEMPORARY);
7942 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7943 return NS_OK;
7944 }
7945 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
7946 }
7947
7948 // Hack: ContinueOnStartRequest2 uses NS_OK to detect successful redirects,
7949 // so we distinguish this codepath (a non-redirect that's processing
7950 // normally) by passing in a bogus error code.
7951 return ContinueOnStartRequest2(NS_BINDING_FAILED);
7952}
7953
7954nsresult nsHttpChannel::ContinueOnStartRequest2(nsresult result) {
7955 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
7956 // Redirect has passed through, we don't want to go on with this
7957 // channel. It will now be canceled by the redirect handling code
7958 // that called this function.
7959 return NS_OK;
7960 }
7961
7962 // on proxy errors, try to failover
7963 if (mConnectionInfo->ProxyInfo() &&
7964 (mStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
7965 mStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
7966 mStatus == NS_ERROR_NET_TIMEOUT || mStatus == NS_ERROR_NET_RESET)) {
7967 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
7968 if (NS_SUCCEEDED(ProxyFailover())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ProxyFailover()))
, 1)))
) {
7969 mProxyConnectResponseCode = 0;
7970 return NS_OK;
7971 }
7972 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
7973 }
7974
7975 // Hack: ContinueOnStartRequest3 uses NS_OK to detect successful redirects,
7976 // so we distinguish this codepath (a non-redirect that's processing
7977 // normally) by passing in a bogus error code.
7978 return ContinueOnStartRequest3(NS_BINDING_FAILED);
7979}
7980
7981nsresult nsHttpChannel::ContinueOnStartRequest3(nsresult result) {
7982 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
7983 // Redirect has passed through, we don't want to go on with this
7984 // channel. It will now be canceled by the redirect handling code
7985 // that called this function.
7986 return NS_OK;
7987 }
7988
7989 return ContinueOnStartRequest4(NS_OK);
7990}
7991
7992nsresult nsHttpChannel::ContinueOnStartRequest4(nsresult result) {
7993 LOG(("nsHttpChannel::ContinueOnStartRequest4 [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::ContinueOnStartRequest4 [this=%p]", this); }
} while (0)
;
7994
7995 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && mResponseHead && mAuthProvider) {
7996 uint32_t httpStatus = mResponseHead->Status();
7997 if (httpStatus != 401 && httpStatus != 407) {
7998 nsresult rv = mAuthProvider->CheckForSuperfluousAuth();
7999 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8000 mStatus = rv;
8001 LOG((" CheckForSuperfluousAuth 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
, " CheckForSuperfluousAuth failed (%08x)", static_cast<uint32_t
>(rv)); } } while (0)
8002 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
, " CheckForSuperfluousAuth failed (%08x)", static_cast<uint32_t
>(rv)); } } while (0)
;
8003 }
8004 }
8005 }
8006
8007 return CallOnStartRequest();
8008}
8009
8010static void ReportHTTPSRRTelemetry(
8011 const Maybe<nsCOMPtr<nsIDNSHTTPSSVCRecord>>& aMaybeRecord) {
8012 bool hasHTTPSRR = aMaybeRecord && (aMaybeRecord.ref() != nullptr);
8013 if (!hasHTTPSRR) {
8014 mozilla::glean::networking::https_rr_presented.Get("none"_ns).Add(1);
8015 return;
8016 }
8017
8018 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& record = aMaybeRecord.ref();
8019 nsCOMPtr<nsISVCBRecord> svcbRecord;
8020 if (NS_SUCCEEDED(record->GetServiceModeRecord(false, false,((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
8021 getter_AddRefs(svcbRecord)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
) {
8022 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "svcbRecord"
")"); do { *((volatile int*)__null) = 8022; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8023
8024 Maybe<std::tuple<nsCString, SupportedAlpnRank>> alpn =
8025 svcbRecord->GetAlpn();
8026 bool isHttp3 = alpn ? IsHttp3(std::get<1>(*alpn)) : false;
8027 mozilla::glean::networking::https_rr_presented
8028 .Get(isHttp3 ? "presented_with_http3"_ns : "presented"_ns)
8029 .Add(1);
8030 }
8031}
8032
8033static void RecordHttpChanDispositionGlean(ChannelDisposition chanDisposition) {
8034 switch (chanDisposition) {
8035 case kHttpCanceled:
8036 mozilla::glean::networking::http_channel_disposition
8037 .Get("http_cancelled"_ns)
8038 .Add(1);
8039 break;
8040 case kHttpDisk:
8041 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
8042 .Add(1);
8043 break;
8044 case kHttpNetOK:
8045 mozilla::glean::networking::http_channel_disposition.Get("http_net_ok"_ns)
8046 .Add(1);
8047 break;
8048 case kHttpNetEarlyFail:
8049 mozilla::glean::networking::http_channel_disposition
8050 .Get("http_net_early_fail"_ns)
8051 .Add(1);
8052 break;
8053 case kHttpNetLateFail:
8054 mozilla::glean::networking::http_channel_disposition
8055 .Get("http_net_late_fail"_ns)
8056 .Add(1);
8057 break;
8058 case kHttpsCanceled:
8059 mozilla::glean::networking::http_channel_disposition
8060 .Get("https_cancelled"_ns)
8061 .Add(1);
8062 break;
8063 case kHttpsDisk:
8064 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
8065 .Add(1);
8066 break;
8067 case kHttpsNetOK:
8068 mozilla::glean::networking::http_channel_disposition
8069 .Get("https_net_ok"_ns)
8070 .Add(1);
8071 break;
8072 case kHttpsNetEarlyFail:
8073 mozilla::glean::networking::http_channel_disposition
8074 .Get("https_net_early_fail"_ns)
8075 .Add(1);
8076 break;
8077 case kHttpsNetLateFail:
8078 mozilla::glean::networking::http_channel_disposition
8079 .Get("https_net_late_fail"_ns)
8080 .Add(1);
8081 break;
8082 default:
8083 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for chanDisposition"
")"); do { *((volatile int*)__null) = 8083; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8084 }
8085}
8086
8087static nsLiteralCString HttpChanDispositionToTelemetryLabel(
8088 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE upgradeChanDisposition) {
8089 if (upgradeChanDisposition ==
8090 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::cancel) {
8091 return "cancel"_ns;
8092 }
8093 if (upgradeChanDisposition ==
8094 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::disk) {
8095 return "disk"_ns;
8096 }
8097 if (upgradeChanDisposition ==
8098 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::netOk) {
8099 return "net_ok"_ns;
8100 }
8101 if (upgradeChanDisposition ==
8102 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::netEarlyFail) {
8103 return "net_early_fail"_ns;
8104 }
8105 if (upgradeChanDisposition ==
8106 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::netLateFail) {
8107 return "net_late_fail"_ns;
8108 }
8109
8110 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for upgradeChanDecomposition"
")"); do { *((volatile int*)__null) = 8110; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8111 return "other"_ns;
8112}
8113
8114nsresult nsHttpChannel::LogConsoleError(const char* aTag) {
8115 nsCOMPtr<nsIConsoleService> console(mozilla::components::Console::Service());
8116 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
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8116); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
8117
8118 nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
8119 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
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8119); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
8120 uint64_t innerWindowID = loadInfo->GetInnerWindowID();
8121
8122 nsAutoString errorText;
8123 nsresult rv = nsContentUtils::GetLocalizedString(
8124 nsContentUtils::eNECKO_PROPERTIES, aTag, errorText);
8125 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8125); return rv; } } while (false)
;
8126
8127 nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1"));
8128 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
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8128); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
8129
8130 rv =
8131 error->InitWithSourceURI(errorText, mURI, 0, 0, nsIScriptError::errorFlag,
8132 "Invalid HTTP Status Lines"_ns, innerWindowID);
8133 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8133); return rv; } } while (false)
;
8134 console->LogMessage(error);
8135 return NS_OK;
8136}
8137
8138static void RecordHTTPSUpgradeTelemetry(nsIURI* aURI, nsILoadInfo* aLoadInfo) {
8139 // we record https telemetry only for top-level loads
8140 if (aLoadInfo->GetExternalContentPolicyType() !=
8141 ExtContentPolicy::TYPE_DOCUMENT) {
8142 return;
8143 }
8144
8145 // exempt loopback addresses because we only want to record telemetry
8146 // for actual web requests
8147 if (nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI)) {
8148 return;
8149 }
8150
8151 // todo: for now we don't record form submissions, only
8152 // top-level document loads. Once Bug 1720500 is fixed, we can
8153 // consider recording form submissions too.
8154 if (aLoadInfo->GetIsFormSubmission()) {
8155 return;
8156 }
8157
8158 bool isHTTPS = aURI->SchemeIs("https");
8159
8160 nsILoadInfo::HTTPSUpgradeTelemetryType httpsTelemetry =
8161 aLoadInfo->GetHttpsUpgradeTelemetry();
8162 switch (httpsTelemetry) {
8163 case nsILoadInfo::NOT_INITIALIZED: {
8164 if (isHTTPS) {
8165 // Bug 1912222: We should never encounter NOT_INITIALIZED values,
8166 // though we still want to know whether those loads are HTTPS
8167 // or not. Eventually we'll want to remove this if-clause
8168 // again and only report "not_initialized".
8169 mozilla::glean::networking::http_to_https_upgrade_reason
8170 .Get("not_initialized_https"_ns)
8171 .Add(1);
8172 return;
8173 }
8174 mozilla::glean::networking::http_to_https_upgrade_reason
8175 .Get("not_initialized"_ns)
8176 .Add(1);
8177 break;
8178 }
8179 case nsILoadInfo::NO_UPGRADE: {
8180 if (isHTTPS) {
8181 // Bug 1912222: We should rearely encounter NO_UPGRADE values, though
8182 // we still want to ensure those are not HTTPS. Eventually we'll want
8183 // to remove this if-clause again and only report "no_upgrade".
8184 mozilla::glean::networking::http_to_https_upgrade_reason
8185 .Get("no_upgrade_https"_ns)
8186 .Add(1);
8187 return;
8188 }
8189 mozilla::glean::networking::http_to_https_upgrade_reason
8190 .Get("no_upgrade"_ns)
8191 .Add(1);
8192 break;
8193 }
8194 case nsILoadInfo::ALREADY_HTTPS:
8195 mozilla::glean::networking::http_to_https_upgrade_reason
8196 .Get("already_https"_ns)
8197 .Add(1);
8198 break;
8199 case nsILoadInfo::HSTS:
8200 mozilla::glean::networking::http_to_https_upgrade_reason.Get("hsts"_ns)
8201 .Add(1);
8202 break;
8203 case nsILoadInfo::HTTPS_ONLY_UPGRADE:
8204 mozilla::glean::networking::http_to_https_upgrade_reason
8205 .Get("https_only_upgrade"_ns)
8206 .Add(1);
8207 break;
8208 case nsILoadInfo::HTTPS_ONLY_UPGRADE_DOWNGRADE:
8209 mozilla::glean::networking::http_to_https_upgrade_reason
8210 .Get("https_only_upgrade_downgrade"_ns)
8211 .Add(1);
8212 break;
8213 case nsILoadInfo::HTTPS_FIRST_UPGRADE:
8214 mozilla::glean::networking::http_to_https_upgrade_reason
8215 .Get("https_first_upgrade"_ns)
8216 .Add(1);
8217 break;
8218 case nsILoadInfo::HTTPS_FIRST_UPGRADE_DOWNGRADE:
8219 mozilla::glean::networking::http_to_https_upgrade_reason
8220 .Get("https_first_upgrade_downgrade"_ns)
8221 .Add(1);
8222 break;
8223 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE:
8224 mozilla::glean::networking::http_to_https_upgrade_reason
8225 .Get("https_first_schemeless_upgrade"_ns)
8226 .Add(1);
8227 break;
8228 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE_DOWNGRADE:
8229 mozilla::glean::networking::http_to_https_upgrade_reason
8230 .Get("https_first_schemeless_upgrade_downgrade"_ns)
8231 .Add(1);
8232 break;
8233 case nsILoadInfo::CSP_UIR:
8234 mozilla::glean::networking::http_to_https_upgrade_reason.Get("csp_uir"_ns)
8235 .Add(1);
8236 break;
8237 case nsILoadInfo::HTTPS_RR:
8238 mozilla::glean::networking::http_to_https_upgrade_reason
8239 .Get("https_rr"_ns)
8240 .Add(1);
8241 break;
8242 case nsILoadInfo::WEB_EXTENSION_UPGRADE:
8243 mozilla::glean::networking::http_to_https_upgrade_reason
8244 .Get("web_extension_upgrade"_ns)
8245 .Add(1);
8246 break;
8247 case nsILoadInfo::UPGRADE_EXCEPTION:
8248 mozilla::glean::networking::http_to_https_upgrade_reason
8249 .Get("upgrade_exception"_ns)
8250 .Add(1);
8251 break;
8252 default:
8253 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?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"what telemetry flag is set to end up here?" ")"); do { *((volatile
int*)__null) = 8253; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8254 }
8255}
8256
8257NS_IMETHODIMPnsresult
8258nsHttpChannel::OnStopRequest(nsIRequest* request, nsresult status) {
8259 AUTO_PROFILER_LABEL("nsHttpChannel::OnStopRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject8259( "nsHttpChannel::OnStopRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
8260
8261 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)
8262 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)
;
8263
8264 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)
8265 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)
;
8266
8267 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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { *((volatile int*)__null) = 8268; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8268 "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"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { *((volatile int*)__null) = 8268; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8269
8270 if (mStatus == NS_ERROR_PARSING_HTTP_STATUS_LINE) {
8271 Unused << LogConsoleError("InvalidHTTPResponseStatusLine");
8272 }
8273
8274 if (WRONG_RACING_RESPONSE_SOURCE(request)(mRaceCacheWithNetwork && (((mFirstResponseSource == RESPONSE_FROM_CACHE
) && ((request) != mCachePump)) || ((mFirstResponseSource
== RESPONSE_FROM_NETWORK) && ((request) != mTransactionPump
))))
) {
8275 return NS_OK;
8276 }
8277
8278 // It's possible that LoadUseHTTPSSVC() is false, but we already have
8279 // mHTTPSSVCRecord.
8280 if (LoadUseHTTPSSVC() || mHTTPSSVCRecord) {
8281 ReportHTTPSRRTelemetry(mHTTPSSVCRecord);
8282 }
8283
8284 // If this load failed because of a security error, it may be because we
8285 // are in a captive portal - trigger an async check to make sure.
8286 int32_t nsprError = -1 * NS_ERROR_GET_CODE(status);
8287 if (mozilla::psm::IsNSSErrorCode(nsprError) && IsHTTPS()) {
8288 gIOService->RecheckCaptivePortal();
8289 }
8290
8291 if (LoadTimingEnabled() && request == mCachePump) {
8292 mCacheReadEnd = TimeStamp::Now();
8293 }
8294
8295 // allow content to be cached if it was loaded successfully (bug #482935)
8296 bool contentComplete = NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)));
8297
8298 // honor the cancelation status even if the underlying transaction
8299 // completed.
8300 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) status = mStatus;
8301
8302 if (mLoadInfo->TriggeringPrincipal()->IsSystemPrincipal()) {
8303 ReportSystemChannelTelemetry(status);
8304 }
8305
8306 if (LoadCachedContentIsPartial()) {
8307 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
8308 // mTransactionPump should be suspended
8309 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ *((volatile int*)__null) = 8310; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8310 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ *((volatile int*)__null) = 8310; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8311
8312 if (request == mCachePump) {
8313 bool streamDone;
8314 status = OnDoneReadingPartialCacheEntry(&streamDone);
8315 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) && !streamDone) return status;
8316 // otherwise, fall through and fire OnStopRequest...
8317 } else if (request == mTransactionPump) {
8318 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { *((volatile int*)__null) = 8318; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8319 } else {
8320 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8320); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected request" ")"); do { *
((volatile int*)__null) = 8320; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
8321 }
8322 }
8323 // Do not to leave the transaction in a suspended state in error cases.
8324 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) && mTransaction) {
8325 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, status);
8326 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8327 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)
;
8328 }
8329 }
8330 }
8331
8332 nsCOMPtr<nsICompressConvStats> conv = do_QueryInterface(mCompressListener);
8333 if (conv) {
8334 conv->GetDecodedDataLength(&mDecodedBodySize);
8335 }
8336
8337 bool isFromNet = request == mTransactionPump;
8338
8339 if (mTransaction) {
8340 // determine if we should call DoAuthRetry
8341 bool authRetry = (mAuthRetryPending && NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) &&
8342 // we should only auth retry in this channel if are not
8343 // redirecting a new channel for authentication retries
8344 !StaticPrefs::network_auth_use_redirect_for_retries());
8345
8346 StoreStronglyFramed(mTransaction->ResponseIsComplete());
8347 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)
8348 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)
;
8349
8350 // Save the reference of |mTransaction| to |transactionWithStickyConn|
8351 // when it has a sticky connection.
8352 // In the case we need to retry an authentication request, we need to
8353 // reuse the connection of |transactionWithStickyConn|.
8354 RefPtr<HttpTransactionShell> transactionWithStickyConn;
8355 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
8356 mTransaction->HasStickyConnection()) {
8357 transactionWithStickyConn = mTransaction;
8358 // Make sure we use the updated caps and connection info from transaction.
8359 // We read these values when the transaction is already closed, so there
8360 // should be no race.
8361 if (mTransaction->Http2Disabled()) {
8362 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
8363 }
8364 if (mTransaction->Http3Disabled()) {
8365 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
8366 }
8367 mConnectionInfo = mTransaction->GetConnInfo();
8368 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)
8369 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)
;
8370 }
8371
8372 // this code relies on the code in nsHttpTransaction::Close, which
8373 // tests for NS_HTTP_STICKY_CONNECTION to determine whether or not to
8374 // keep the connection around after the transaction is finished.
8375 //
8376 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)
8377 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)
8378 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)
;
8379 // We must check caps for stickinness also on the transaction because it
8380 // might have been updated by the transaction itself during inspection of
8381 // the reposnse headers yet on the socket thread (found connection based
8382 // auth schema).
8383
8384 if ((NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) && transactionWithStickyConn) {
8385 // Close (don't reuse) the sticky connection if this channel has been
8386 // cancelled. There are proxy servers known to get confused when we send
8387 // a new request over such a half-stated connection.
8388 if (!LoadAuthConnectionRestartable()) {
8389 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)
;
8390 transactionWithStickyConn->DontReuseConnection();
8391 }
8392 }
8393
8394 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) {
8395 mTransaction->SetH2WSConnRefTaken();
8396 }
8397
8398 mTransferSize = mTransaction->GetTransferSize();
8399 mRequestSize = mTransaction->GetRequestSize();
8400
8401 RecordHTTPSUpgradeTelemetry(mURI, mLoadInfo);
8402
8403 // If we are using the transaction to serve content, we also save the
8404 // time since async open in the cache entry so we can compare telemetry
8405 // between cache and net response.
8406 // Do not store the time of conditional requests because even if we
8407 // fetch the data from the server, the time includes loading of the old
8408 // cache entry which would skew the network load time.
8409 if (request == mTransactionPump && mCacheEntry && !mDidReval &&
8410 !LoadCustomConditionalRequest() && !mAsyncOpenTime.IsNull() &&
8411 !mOnStartRequestTimestamp.IsNull()) {
8412 uint64_t onStartTime =
8413 (mOnStartRequestTimestamp - mAsyncOpenTime).ToMilliseconds();
8414 uint64_t onStopTime =
8415 (TimeStamp::Now() - mAsyncOpenTime).ToMilliseconds();
8416 Unused << mCacheEntry->SetNetworkTimes(onStartTime, onStopTime);
8417 }
8418
8419 mResponseTrailers = mTransaction->TakeResponseTrailers();
8420
8421 if (nsIOService::UseSocketProcess() && mTransaction) {
8422 mOnStopRequestStartTime = mTransaction->GetOnStopRequestStartTime();
8423 if (!mOnStopRequestStartTime.IsNull()) {
8424 PerfStats::RecordMeasurement(
8425 PerfStats::Metric::OnStopRequestSocketToParent,
8426 TimeStamp::Now() - mOnStopRequestStartTime);
8427 }
8428 } else {
8429 mOnStopRequestStartTime = TimeStamp::Now();
8430 }
8431
8432 // at this point, we're done with the transaction
8433 mTransactionTimings = mTransaction->Timings();
8434 mTransaction = nullptr;
8435 mTransactionPump = nullptr;
8436
8437 // We no longer need the dns prefetch object
8438 if (mDNSPrefetch && mDNSPrefetch->TimingsValid() &&
8439 !mTransactionTimings.requestStart.IsNull() &&
8440 !mTransactionTimings.connectStart.IsNull() &&
8441 mDNSPrefetch->EndTimestamp() <= mTransactionTimings.connectStart) {
8442 // We only need the domainLookup timestamps when not using a
8443 // persistent connection, meaning if the endTimestamp < connectStart
8444 mTransactionTimings.domainLookupStart = mDNSPrefetch->StartTimestamp();
8445 mTransactionTimings.domainLookupEnd = mDNSPrefetch->EndTimestamp();
8446 }
8447 mDNSPrefetch = nullptr;
8448
8449 // handle auth retry...
8450 if (authRetry) {
8451 mAuthRetryPending = false;
8452 auto continueOSR = [authRetry, isFromNet, contentComplete,
8453 transactionWithStickyConn](auto* self,
8454 nsresult aStatus) {
8455 return self->ContinueOnStopRequestAfterAuthRetry(
8456 aStatus, authRetry, isFromNet, contentComplete,
8457 transactionWithStickyConn);
8458 };
8459 status = DoAuthRetry(transactionWithStickyConn, continueOSR);
8460 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
8461 return NS_OK;
8462 }
8463 }
8464 return ContinueOnStopRequestAfterAuthRetry(status, authRetry, isFromNet,
8465 contentComplete,
8466 transactionWithStickyConn);
8467 }
8468
8469 return ContinueOnStopRequest(status, isFromNet, contentComplete);
8470}
8471
8472nsresult nsHttpChannel::ContinueOnStopRequestAfterAuthRetry(
8473 nsresult aStatus, bool aAuthRetry, bool aIsFromNet, bool aContentComplete,
8474 HttpTransactionShell* aTransWithStickyConn) {
8475 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
8476 ("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)
8477 "[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)
8478 " 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)
8479 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)
8480 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)
;
8481
8482 if (aAuthRetry && NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
8483 return NS_OK;
8484 }
8485
8486 // If DoAuthRetry failed, or if we have been cancelled since showing
8487 // the auth. dialog, then we need to send OnStartRequest now
8488 if (aAuthRetry || (mAuthRetryPending && NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0))))) {
8489 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8489); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))"
") (" "should have a failure code here" ")"); do { *((volatile
int*)__null) = 8489; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8490 // NOTE: since we have a failure status, we can ignore the return
8491 // value from onStartRequest.
8492 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)
8493 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)
;
8494 if (mListener) {
8495 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8496); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { *
((volatile int*)__null) = 8496; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
8496 "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8496); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { *
((volatile int*)__null) = 8496; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
8497 if (!LoadOnStartRequestCalled()) {
8498 nsCOMPtr<nsIStreamListener> listener(mListener);
8499 StoreOnStartRequestCalled(true);
8500 listener->OnStartRequest(this);
8501 }
8502 } else {
8503 StoreOnStartRequestCalled(true);
8504 NS_WARNING("OnStartRequest skipped because of null listener")NS_DebugBreak(NS_DEBUG_WARNING, "OnStartRequest skipped because of null listener"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8504)
;
8505 }
8506 mAuthRetryPending = false;
8507 }
8508
8509 // if this transaction has been replaced, then bail.
8510 if (LoadTransactionReplaced()) {
8511 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)
;
8512 // This was just the network check for a 304 response.
8513 mFirstResponseSource = RESPONSE_PENDING;
8514 return NS_OK;
8515 }
8516
8517 bool upgradeWebsocket = mUpgradeProtocolCallback && aTransWithStickyConn &&
8518 mResponseHead &&
8519 ((mResponseHead->Status() == 101 &&
8520 mResponseHead->Version() == HttpVersion::v1_1) ||
8521 (mResponseHead->Status() == 200 &&
8522 mResponseHead->Version() == HttpVersion::v2_0));
8523
8524 bool upgradeConnect = mUpgradeProtocolCallback && aTransWithStickyConn &&
8525 (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) && mResponseHead &&
8526 mResponseHead->Status() == 200;
8527
8528 if (upgradeWebsocket || upgradeConnect) {
8529 if (nsIOService::UseSocketProcess() && upgradeConnect) {
8530 // TODO: Support connection upgrade for socket process in bug 1632809.
8531 Unused << mUpgradeProtocolCallback->OnUpgradeFailed(
8532 NS_ERROR_NOT_IMPLEMENTED);
8533 return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
8534 }
8535
8536 nsresult rv = gHttpHandler->CompleteUpgrade(aTransWithStickyConn,
8537 mUpgradeProtocolCallback);
8538 mUpgradeProtocolCallback = nullptr;
8539 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8540 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)
8541 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)
;
8542
8543 // This ensures that WebSocketChannel::OnStopRequest will be
8544 // called with an error so the session is properly aborted.
8545 aStatus = rv;
8546 }
8547 }
8548
8549 return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
8550}
8551
8552nsresult nsHttpChannel::ContinueOnStopRequest(nsresult aStatus, bool aIsFromNet,
8553 bool aContentComplete) {
8554 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
8555 ("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)
8556 "[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)
8557 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)
;
8558
8559 // HTTP_CHANNEL_DISPOSITION TELEMETRY
8560 ChannelDisposition chanDisposition = kHttpCanceled;
8561 // HTTP_CHANNEL_DISPOSITION_UPGRADE TELEMETRY
8562 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE upgradeChanDisposition =
8563 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::cancel;
8564
8565 // HTTP 0.9 is more likely to be an error than really 0.9, so count it that
8566 // way
8567 if (mCanceled) {
8568 chanDisposition = kHttpCanceled;
8569 upgradeChanDisposition =
8570 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::cancel;
8571 } else if (!LoadUsedNetwork() ||
8572 (mRaceCacheWithNetwork &&
8573 mFirstResponseSource == RESPONSE_FROM_CACHE)) {
8574 chanDisposition = kHttpDisk;
8575 upgradeChanDisposition =
8576 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::disk;
8577 } else if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) && mResponseHead &&
8578 mResponseHead->Version() != HttpVersion::v0_9) {
8579 chanDisposition = kHttpNetOK;
8580 upgradeChanDisposition =
8581 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::netOk;
8582 } else if (!mTransferSize) {
8583 chanDisposition = kHttpNetEarlyFail;
8584 upgradeChanDisposition =
8585 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::netEarlyFail;
8586 } else {
8587 chanDisposition = kHttpNetLateFail;
8588 upgradeChanDisposition =
8589 Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::netLateFail;
8590 }
8591 // Browser upgrading only happens on HTTPS pages for mixed passive content
8592 // when upgrading is enabled.
8593 nsCString upgradeKey;
8594 nsLiteralCString upgradeChanDispositionLabel =
8595 HttpChanDispositionToTelemetryLabel(upgradeChanDisposition);
8596 if (IsHTTPS()) {
8597 // Browser upgrading is disabled and the content is already HTTPS
8598 upgradeKey = "disabledNoReason"_ns;
8599 // Checks "security.mixed_content.upgrade_display_content" is true
8600 if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
8601 if (mLoadInfo->GetBrowserUpgradeInsecureRequests()) {
8602 // HTTP content the browser has upgraded to HTTPS
8603 mozilla::glean::networking::http_channel_disposition_enabled_upgrade
8604 .Get(upgradeChanDispositionLabel)
8605 .Add(1);
8606 upgradeKey = "enabledUpgrade"_ns;
8607 } else {
8608 // Content wasn't upgraded but is already HTTPS
8609 mozilla::glean::networking::http_channel_disposition_enabled_no_reason
8610 .Get(upgradeChanDispositionLabel)
8611 .Add(1);
8612 upgradeKey = "enabledNoReason"_ns;
8613 }
8614 } else {
8615 mozilla::glean::networking::http_channel_disposition_disabled_no_reason
8616 .Get(upgradeChanDispositionLabel)
8617 .Add(1);
8618 }
8619 // shift http to https disposition enums
8620 chanDisposition =
8621 static_cast<ChannelDisposition>(chanDisposition + kHttpsCanceled);
8622 } else if (mLoadInfo->GetBrowserWouldUpgradeInsecureRequests()) {
8623 // HTTP content the browser would upgrade to HTTPS if upgrading was
8624 // enabled
8625 mozilla::glean::networking::http_channel_disposition_disabled_upgrade
8626 .Get(upgradeChanDispositionLabel)
8627 .Add(1);
8628 upgradeKey = "disabledUpgrade"_ns;
8629 } else if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
8630 // HTTP content that wouldn't upgrade
8631 mozilla::glean::networking::http_channel_disposition_enabled_wont
8632 .Get(upgradeChanDispositionLabel)
8633 .Add(1);
8634 upgradeKey = "enabledWont"_ns;
8635 } else {
8636 mozilla::glean::networking::http_channel_disposition_disabled_wont
8637 .Get(upgradeChanDispositionLabel)
8638 .Add(1);
8639 upgradeKey = "disabledWont"_ns;
8640 }
8641
8642 Telemetry::AccumulateCategoricalKeyed(upgradeKey, upgradeChanDisposition);
8643
8644 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)
8645 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)
;
8646 Telemetry::Accumulate(Telemetry::HTTP_CHANNEL_DISPOSITION, chanDisposition);
8647 RecordHttpChanDispositionGlean(chanDisposition);
8648
8649 // Collect specific telemetry for measuring image, video, audio
8650 // success/failure rates in regular browsing mode and when auto upgrading of
8651 // subresources is enabled. Note that we only evaluate actual image types, not
8652 // favicons.
8653 nsContentPolicyType internalLoadType;
8654 mLoadInfo->GetInternalContentPolicyType(&internalLoadType);
8655 bool statusIsSuccess = NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)));
8656 if (internalLoadType == nsIContentPolicy::TYPE_INTERNAL_IMAGE ||
8657 internalLoadType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD) {
8658 if (mLoadInfo->GetBrowserDidUpgradeInsecureRequests()) {
8659 Telemetry::AccumulateCategorical(
8660 statusIsSuccess
8661 ? Telemetry::LABELS_MIXED_CONTENT_IMAGES::ImgUpSuccess
8662 : Telemetry::LABELS_MIXED_CONTENT_IMAGES::ImgUpFailure);
8663 } else {
8664 Telemetry::AccumulateCategorical(
8665 statusIsSuccess
8666 ? Telemetry::LABELS_MIXED_CONTENT_IMAGES::ImgNoUpSuccess
8667 : Telemetry::LABELS_MIXED_CONTENT_IMAGES::ImgNoUpFailure);
8668 }
8669 }
8670 if (internalLoadType == nsIContentPolicy::TYPE_INTERNAL_VIDEO) {
8671 if (mLoadInfo->GetBrowserDidUpgradeInsecureRequests()) {
8672 Telemetry::AccumulateCategorical(
8673 statusIsSuccess
8674 ? Telemetry::LABELS_MIXED_CONTENT_VIDEO::VideoUpSuccess
8675 : Telemetry::LABELS_MIXED_CONTENT_VIDEO::VideoUpFailure);
8676 } else {
8677 Telemetry::AccumulateCategorical(
8678 statusIsSuccess
8679 ? Telemetry::LABELS_MIXED_CONTENT_VIDEO::VideoNoUpSuccess
8680 : Telemetry::LABELS_MIXED_CONTENT_VIDEO::VideoNoUpFailure);
8681 }
8682 }
8683 if (internalLoadType == nsIContentPolicy::TYPE_INTERNAL_AUDIO) {
8684 if (mLoadInfo->GetBrowserDidUpgradeInsecureRequests()) {
8685 Telemetry::AccumulateCategorical(
8686 statusIsSuccess
8687 ? Telemetry::LABELS_MIXED_CONTENT_AUDIO::AudioUpSuccess
8688 : Telemetry::LABELS_MIXED_CONTENT_AUDIO::AudioUpFailure);
8689 } else {
8690 Telemetry::AccumulateCategorical(
8691 statusIsSuccess
8692 ? Telemetry::LABELS_MIXED_CONTENT_AUDIO::AudioNoUpSuccess
8693 : Telemetry::LABELS_MIXED_CONTENT_AUDIO::AudioNoUpFailure);
8694 }
8695 }
8696
8697 // if needed, check cache entry has all data we expect
8698 if (mCacheEntry && mCachePump && LoadConcurrentCacheAccess() &&
8699 aContentComplete) {
8700 int64_t size, contentLength;
8701 nsresult rv = CheckPartial(mCacheEntry, &size, &contentLength);
8702 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8703 if (size == int64_t(-1)) {
8704 // mayhemer TODO - we have to restart read from cache here at the size
8705 // offset
8706 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")")
; do { *((volatile int*)__null) = 8706; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8707 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
8708 (" 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)
8709 "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)
;
8710 } else if (contentLength != int64_t(-1) && contentLength != size) {
8711 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)
;
8712 mCachedResponseHead = std::move(mResponseHead);
8713 // Ignore zero partial length because we also want to resume when
8714 // no data at all has been read from the cache.
8715 rv = MaybeSetupByteRangeRequest(size, contentLength, true);
8716 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest()) {
8717 // Prevent read from cache again
8718 mCachedContentIsValid = false;
8719 StoreCachedContentIsPartial(1);
8720
8721 // We are about to perform a different network request.
8722 // We must set mRaceCacheWithNetwork to false because otherwise
8723 // we would ignore the network response thinking we didn't need it.
8724 mRaceCacheWithNetwork = false;
8725
8726 // Perform the range request
8727 rv = ContinueConnect();
8728 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8729 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)
;
8730 mCachePump = nullptr;
8731 return NS_OK;
8732 }
8733 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)
8734 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)
;
8735 aStatus = NS_ERROR_NET_INTERRUPT;
8736 } else {
8737 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)
8738 ", 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)
8739 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)
;
8740 }
8741 }
8742 }
8743 }
8744
8745 StoreIsPending(false);
8746 mStatus = aStatus;
8747
8748 // perform any final cache operations before we close the cache entry.
8749 if (mCacheEntry && LoadRequestTimeInitialized()) {
8750 // New implementation just returns value of the !LoadCacheEntryIsReadOnly()
8751 // flag passed in. Old implementation checks on nsICache::ACCESS_WRITE
8752 // flag.
8753
8754 // Assume that write access is granted
8755 if (!LoadCacheEntryIsReadOnly()) {
8756 nsresult rv = FinalizeCacheEntry();
8757 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8758 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)
;
8759 }
8760 }
8761 }
8762
8763 ReportRcwnStats(aIsFromNet);
8764
8765 // Register entry to the PerformanceStorage resource timing
8766 MaybeReportTimingData();
8767
8768 MaybeFlushConsoleReports();
8769
8770 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
8771 // These do allocations/frees/etc; avoid if not active
8772 mEndMarkerAdded = true;
8773
8774 nsAutoCString requestMethod;
8775 GetRequestMethod(requestMethod);
8776
8777 int32_t priority = PRIORITY_NORMAL;
8778 GetPriority(&priority);
8779
8780 uint64_t size = 0;
8781 GetEncodedBodySize(&size);
8782
8783 nsAutoCString contentType;
8784 if (mResponseHead) {
8785 mResponseHead->ContentType(contentType);
8786 }
8787 profiler_add_network_marker(
8788 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_STOP,
8789 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
8790 mLoadInfo->GetInnerWindowID(),
8791 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(),
8792 &mTransactionTimings, std::move(mSource),
8793 Some(nsDependentCString(contentType.get())));
8794 }
8795
8796 if (mAuthRetryPending &&
8797 StaticPrefs::network_auth_use_redirect_for_retries()) {
8798 nsresult rv = OpenRedirectChannel(aStatus);
8799 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)
8800 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)
;
8801 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8802 if (mListener) {
8803 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8804); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { *
((volatile int*)__null) = 8804; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
8804 "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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8804); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { *
((volatile int*)__null) = 8804; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
8805 if (!LoadOnStartRequestCalled()) {
8806 nsCOMPtr<nsIStreamListener> listener(mListener);
8807 StoreOnStartRequestCalled(true);
8808 listener->OnStartRequest(this);
8809 }
8810 } else {
8811 StoreOnStartRequestCalled(true);
8812 NS_WARNING("OnStartRequest skipped because of null listener")NS_DebugBreak(NS_DEBUG_WARNING, "OnStartRequest skipped because of null listener"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8812)
;
8813 }
8814 }
8815 mAuthRetryPending = false;
8816 }
8817
8818 if (StaticPrefs::network_http_network_error_logging_enabled() &&
8819 LoadUsedNetwork() && !mReportedNEL) {
8820 if (nsCOMPtr<nsINetworkErrorLogging> nel =
8821 components::NetworkErrorLogging::Service()) {
8822 nel->GenerateNELReport(this);
8823 }
8824 mReportedNEL = true;
8825 }
8826
8827 // notify "http-on-before-stop-request" observers
8828 gHttpHandler->OnBeforeStopRequest(this);
8829
8830 if (mListener) {
8831 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)
;
8832 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" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { *((volatile int*)__null) = 8833; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8833 "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" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { *((volatile int*)__null) = 8833; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8834 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { *(
(volatile int*)__null) = 8835; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
8835 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { *(
(volatile int*)__null) = 8835; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
8836 StoreOnStopRequestCalled(true);
8837 mListener->OnStopRequest(this, aStatus);
8838 }
8839 StoreOnStopRequestCalled(true);
8840
8841 // The prefetch needs to be released on the main thread
8842 mDNSPrefetch = nullptr;
8843
8844 mRedirectChannel = nullptr;
8845
8846 // notify "http-on-stop-request" observers
8847 gHttpHandler->OnStopRequest(this);
8848
8849 RemoveAsNonTailRequest();
8850
8851 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref) {
8852 mResponseHead->ClearHeaders();
8853 }
8854 // If a preferred alt-data type was set, this signals the consumer is
8855 // interested in reading and/or writing the alt-data representation.
8856 // We need to hold a reference to the cache entry in case the listener calls
8857 // openAlternativeOutputStream() after CloseCacheEntry() clears mCacheEntry.
8858 if (!mPreferredCachedAltDataTypes.IsEmpty()) {
8859 mAltDataCacheEntry = mCacheEntry;
8860 }
8861
8862 CloseCacheEntry(!aContentComplete);
8863
8864 if (mLoadGroup) {
8865 mLoadGroup->RemoveRequest(this, nullptr, aStatus);
8866 }
8867
8868 // We don't need this info anymore
8869 CleanRedirectCacheChainIfNecessary();
8870
8871 ReleaseListeners();
8872
8873 return NS_OK;
8874}
8875
8876//-----------------------------------------------------------------------------
8877// nsHttpChannel::nsIStreamListener
8878//-----------------------------------------------------------------------------
8879
8880class OnTransportStatusAsyncEvent : public Runnable {
8881 public:
8882 OnTransportStatusAsyncEvent(nsITransportEventSink* aEventSink,
8883 nsresult aTransportStatus, int64_t aProgress,
8884 int64_t aProgressMax)
8885 : Runnable("net::OnTransportStatusAsyncEvent"),
8886 mEventSink(aEventSink),
8887 mTransportStatus(aTransportStatus),
8888 mProgress(aProgress),
8889 mProgressMax(aProgressMax) {
8890 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8890); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "Shouldn't be created on main thread" ")"); do { *((volatile
int*)__null) = 8890; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8891 }
8892
8893 NS_IMETHODvirtual nsresult Run() override {
8894 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should run on main thread" ")"); do { *((volatile int
*)__null) = 8894; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8895 if (mEventSink) {
8896 mEventSink->OnTransportStatus(nullptr, mTransportStatus, mProgress,
8897 mProgressMax);
8898 }
8899 return NS_OK;
8900 }
8901
8902 private:
8903 nsCOMPtr<nsITransportEventSink> mEventSink;
8904 nsresult mTransportStatus;
8905 int64_t mProgress;
8906 int64_t mProgressMax;
8907};
8908
8909NS_IMETHODIMPnsresult
8910nsHttpChannel::OnDataAvailable(nsIRequest* request, nsIInputStream* input,
8911 uint64_t offset, uint32_t count) {
8912 nsresult rv;
8913 AUTO_PROFILER_LABEL("nsHttpChannel::OnDataAvailable", NETWORK)mozilla::AutoProfilerLabel raiiObject8913( "nsHttpChannel::OnDataAvailable"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
8914
8915 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)
8916 " 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)
8917 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)
;
8918
8919 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)
8920 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)
;
8921
8922 // don't send out OnDataAvailable notifications if we've been canceled.
8923 if (mCanceled) return mStatus;
8924
8925 if (mAuthRetryPending || WRONG_RACING_RESPONSE_SOURCE(request)(mRaceCacheWithNetwork && (((mFirstResponseSource == RESPONSE_FROM_CACHE
) && ((request) != mCachePump)) || ((mFirstResponseSource
== RESPONSE_FROM_NETWORK) && ((request) != mTransactionPump
))))
||
8926 (request == mTransactionPump && LoadTransactionReplaced())) {
8927 uint32_t n;
8928 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &n);
8929 }
8930
8931 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!!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8931); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "No response head in ODA!!" ")"); do { *((volatile int
*)__null) = 8931; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8932
8933 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { *((volatile
int*)__null) = 8934; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8934 "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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { *((volatile
int*)__null) = 8934; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8935
8936 mIsReadingFromCache = (request == mCachePump);
8937
8938 if (mListener) {
8939 //
8940 // synthesize transport progress event. we do this here since we want
8941 // to delay OnProgress events until we start streaming data. this is
8942 // crucially important since it impacts the lock icon (see bug 240053).
8943 //
8944 nsresult transportStatus;
8945 if (request == mCachePump) {
8946 transportStatus = NS_NET_STATUS_READING;
8947 } else {
8948 transportStatus = NS_NET_STATUS_RECEIVING_FROM;
8949 }
8950
8951 // mResponseHead may reference new or cached headers, but either way it
8952 // holds our best estimate of the total content length. Even in the case
8953 // of a byte range request, the content length stored in the cached
8954 // response headers is what we want to use here.
8955
8956 int64_t progressMax = -1;
8957 rv = GetContentLength(&progressMax);
8958 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8959 NS_WARNING("GetContentLength failed")NS_DebugBreak(NS_DEBUG_WARNING, "GetContentLength failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8959)
;
8960 }
8961 int64_t progress = mLogicalOffset + count;
8962
8963 if ((progress > progressMax) && (progressMax != -1)) {
8964 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8966)
8965 "unexpected progress values - "NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8966)
8966 "is server exceeding content length?")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8966)
;
8967 }
8968
8969 // make sure params are in range for js
8970 if (!InScriptableRange(progressMax)) {
8971 progressMax = -1;
8972 }
8973
8974 if (!InScriptableRange(progress)) {
8975 progress = -1;
8976 }
8977
8978 if (NS_IsMainThread()) {
8979 OnTransportStatus(nullptr, transportStatus, progress, progressMax);
8980 } else {
8981 rv = NS_DispatchToMainThread(new OnTransportStatusAsyncEvent(
8982 this, transportStatus, progress, progressMax));
8983 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 8983); return rv; } } while (false)
;
8984 }
8985
8986 //
8987 // we have to manually keep the logical offset of the stream up-to-date.
8988 // we cannot depend solely on the offset provided, since we may have
8989 // already streamed some data from another source (see, for example,
8990 // OnDoneReadingPartialCacheEntry).
8991 //
8992 int64_t offsetBefore = 0;
8993 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(input);
8994 if (seekable && NS_FAILED(seekable->Tell(&offsetBefore))((bool)(__builtin_expect(!!(NS_FAILED_impl(seekable->Tell(
&offsetBefore))), 0)))
) {
8995 seekable = nullptr;
8996 }
8997
8998 if (nsIOService::UseSocketProcess() && mTransaction) {
8999 mOnDataAvailableStartTime = mTransaction->GetDataAvailableStartTime();
9000 if (!mOnDataAvailableStartTime.IsNull()) {
9001 PerfStats::RecordMeasurement(
9002 PerfStats::Metric::OnDataAvailableSocketToParent,
9003 TimeStamp::Now() - mOnDataAvailableStartTime);
9004 }
9005 } else {
9006 mOnDataAvailableStartTime = TimeStamp::Now();
9007 }
9008 nsresult rv =
9009 mListener->OnDataAvailable(this, input, mLogicalOffset, count);
9010 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9011 // by contract mListener must read all of "count" bytes, but
9012 // nsInputStreamPump is tolerant to seekable streams that violate that
9013 // and it will redeliver incompletely read data. So we need to do
9014 // the same thing when updating the progress counter to stay in sync.
9015 int64_t offsetAfter, delta;
9016 if (seekable && NS_SUCCEEDED(seekable->Tell(&offsetAfter))((bool)(__builtin_expect(!!(!NS_FAILED_impl(seekable->Tell
(&offsetAfter))), 1)))
) {
9017 delta = offsetAfter - offsetBefore;
9018 if (delta != count) {
9019 count = delta;
9020
9021 NS_WARNING("Listener OnDataAvailable contract violation")NS_DebugBreak(NS_DEBUG_WARNING, "Listener OnDataAvailable contract violation"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9021)
;
9022 nsCOMPtr<nsIConsoleService> consoleService;
9023 consoleService = mozilla::components::Console::Service();
9024 nsAutoString message(nsLiteralString(
9025 u"http channel Listener OnDataAvailable contract violation"));
9026 if (consoleService) {
9027 consoleService->LogStringMessage(message.get());
9028 }
9029 }
9030 }
9031 mLogicalOffset += count;
9032 }
9033
9034 return rv;
9035 }
9036
9037 return NS_ERROR_ABORT;
9038}
9039
9040//-----------------------------------------------------------------------------
9041// nsHttpChannel::nsIThreadRetargetableRequest
9042//-----------------------------------------------------------------------------
9043
9044NS_IMETHODIMPnsresult
9045nsHttpChannel::RetargetDeliveryTo(nsISerialEventTarget* aNewTarget) {
9046 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on main thread only" ")"); do { *((volatile
int*)__null) = 9046; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9047
9048 NS_ENSURE_ARG(aNewTarget)do { if ((__builtin_expect(!!(!(aNewTarget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNewTarget" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9048); return NS_ERROR_INVALID_ARG; } } while (false)
;
9049 if (aNewTarget->IsOnCurrentThread()) {
9050 NS_WARNING("Retargeting delivery to same thread")NS_DebugBreak(NS_DEBUG_WARNING, "Retargeting delivery to same thread"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9050)
;
9051 return NS_OK;
9052 }
9053 if (!mTransactionPump && !mCachePump) {
9054 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)
9055 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)
;
9056 return NS_ERROR_NOT_AVAILABLE;
9057 }
9058
9059 nsresult rv = NS_OK;
9060 // If both cache pump and transaction pump exist, we're probably dealing
9061 // with partially cached content. So, we must be able to retarget both.
9062 nsCOMPtr<nsIThreadRetargetableRequest> retargetableCachePump;
9063 nsCOMPtr<nsIThreadRetargetableRequest> retargetableTransactionPump;
9064 if (mCachePump) {
9065 retargetableCachePump = do_QueryObject(mCachePump);
9066 // nsInputStreamPump should implement this interface.
9067 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableCachePump"
")"); do { *((volatile int*)__null) = 9067; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9068 rv = retargetableCachePump->RetargetDeliveryTo(aNewTarget);
9069 }
9070 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mTransactionPump) {
9071 retargetableTransactionPump = do_QueryObject(mTransactionPump);
9072 // nsInputStreamPump should implement this interface.
9073 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableTransactionPump"
")"); do { *((volatile int*)__null) = 9073; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9074 rv = retargetableTransactionPump->RetargetDeliveryTo(aNewTarget);
9075
9076 // If retarget fails for transaction pump, we must restore mCachePump.
9077 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && retargetableCachePump) {
9078 nsCOMPtr<nsISerialEventTarget> main = GetMainThreadSerialEventTarget();
9079 NS_ENSURE_TRUE(main, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(main)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "main" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9079); return NS_ERROR_UNEXPECTED; } } while (false)
;
9080 rv = retargetableCachePump->RetargetDeliveryTo(main);
9081 }
9082 }
9083 return rv;
9084}
9085
9086NS_IMETHODIMPnsresult
9087nsHttpChannel::GetDeliveryTarget(nsISerialEventTarget** aEventTarget) {
9088 if (mCachePump) {
9089 return mCachePump->GetDeliveryTarget(aEventTarget);
9090 }
9091 if (mTransactionPump) {
9092 nsCOMPtr<nsIThreadRetargetableRequest> request =
9093 do_QueryInterface(mTransactionPump);
9094 return request->GetDeliveryTarget(aEventTarget);
9095 }
9096 return NS_ERROR_NOT_AVAILABLE;
9097}
9098
9099//-----------------------------------------------------------------------------
9100// nsHttpChannel::nsThreadRetargetableStreamListener
9101//-----------------------------------------------------------------------------
9102
9103NS_IMETHODIMPnsresult
9104nsHttpChannel::CheckListenerChain() {
9105 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()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9105); MOZ_PretendNoReturn(); } } while (0)
;
9106 nsresult rv = NS_OK;
9107 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
9108 do_QueryInterface(mListener, &rv);
9109 if (retargetableListener) {
9110 rv = retargetableListener->CheckListenerChain();
9111 }
9112 return rv;
9113}
9114
9115NS_IMETHODIMPnsresult
9116nsHttpChannel::OnDataFinished(nsresult aStatus) {
9117 nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
9118 do_QueryInterface(mListener);
9119
9120 if (listener) {
9121 return listener->OnDataFinished(aStatus);
9122 }
9123
9124 return NS_OK;
9125}
9126
9127//-----------------------------------------------------------------------------
9128// nsHttpChannel::nsITransportEventSink
9129//-----------------------------------------------------------------------------
9130
9131NS_IMETHODIMPnsresult
9132nsHttpChannel::OnTransportStatus(nsITransport* trans, nsresult status,
9133 int64_t progress, int64_t progressMax) {
9134 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be on main thread only" ")"); do { *((volatile
int*)__null) = 9134; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9135 // cache the progress sink so we don't have to query for it each time.
9136 if (!mProgressSink) GetCallback(mProgressSink);
9137
9138 mLastTransportStatus = status;
9139 if (status == NS_NET_STATUS_CONNECTED_TO ||
9140 status == NS_NET_STATUS_WAITING_FOR) {
9141 bool isTrr = false;
9142 bool echConfigUsed = false;
9143 if (mTransaction) {
9144 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
9145 mEffectiveTRRMode, mTRRSkipReason,
9146 echConfigUsed);
9147 } else {
9148 nsCOMPtr<nsISocketTransport> socketTransport = do_QueryInterface(trans);
9149 if (socketTransport) {
9150 socketTransport->GetSelfAddr(&mSelfAddr);
9151 socketTransport->GetPeerAddr(&mPeerAddr);
9152 socketTransport->ResolvedByTRR(&isTrr);
9153 socketTransport->GetEffectiveTRRMode(&mEffectiveTRRMode);
9154 socketTransport->GetEchConfigUsed(&echConfigUsed);
9155 }
9156 }
9157
9158 StoreResolvedByTRR(isTrr);
9159 StoreEchConfigUsed(echConfigUsed);
9160 }
9161
9162 // block socket status event after Cancel or OnStopRequest has been called.
9163 if (mProgressSink && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && LoadIsPending()) {
9164 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)
9165 " 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)
9166 (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)
9167 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)
;
9168
9169 nsAutoCString host;
9170 mURI->GetHost(host);
9171 if (!(mLoadFlags & LOAD_BACKGROUND)) {
9172 mProgressSink->OnStatus(this, status, NS_ConvertUTF8toUTF16(host).get());
9173 } else {
9174 nsCOMPtr<nsIParentChannel> parentChannel;
9175 NS_QueryNotificationCallbacks(this, parentChannel);
9176 // If the event sink is |HttpChannelParent|, we have to send status
9177 // events to it even if LOAD_BACKGROUND is set. |HttpChannelParent|
9178 // needs to be aware of whether the status is
9179 // |NS_NET_STATUS_RECEIVING_FROM| or |NS_NET_STATUS_READING|.
9180 // LOAD_BACKGROUND is checked again in |HttpChannelChild|, so the final
9181 // consumer won't get this event.
9182 if (SameCOMIdentity(parentChannel, mProgressSink)) {
9183 mProgressSink->OnStatus(this, status,
9184 NS_ConvertUTF8toUTF16(host).get());
9185 }
9186 }
9187
9188 if (progress > 0) {
9189 if ((progress > progressMax) && (progressMax != -1)) {
9190 NS_WARNING("unexpected progress values")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9190)
;
9191 }
9192
9193 // Try to get mProgressSink if it was nulled out during OnStatus.
9194 if (!mProgressSink) {
9195 GetCallback(mProgressSink);
9196 }
9197 if (mProgressSink) {
9198 mProgressSink->OnProgress(this, progress, progressMax);
9199 }
9200 }
9201 }
9202
9203 return NS_OK;
9204}
9205
9206//-----------------------------------------------------------------------------
9207// nsHttpChannel::nsICacheInfoChannel
9208//-----------------------------------------------------------------------------
9209
9210NS_IMETHODIMPnsresult
9211nsHttpChannel::IsFromCache(bool* value) {
9212 if (!LoadIsPending()) return NS_ERROR_NOT_AVAILABLE;
9213
9214 if (!mRaceCacheWithNetwork) {
9215 // return false if reading a partial cache entry; the data isn't
9216 // entirely from the cache!
9217 *value = (mCachePump || (mLoadFlags & LOAD_ONLY_IF_MODIFIED)) &&
9218 mCachedContentIsValid && !LoadCachedContentIsPartial();
9219 return NS_OK;
9220 }
9221
9222 // If we are racing network and cache (or skipping the cache)
9223 // we just return the first response source.
9224 *value = mFirstResponseSource == RESPONSE_FROM_CACHE;
9225
9226 return NS_OK;
9227}
9228
9229NS_IMETHODIMPnsresult
9230nsHttpChannel::GetCacheEntryId(uint64_t* aCacheEntryId) {
9231 bool fromCache = false;
9232 if (NS_FAILED(IsFromCache(&fromCache))((bool)(__builtin_expect(!!(NS_FAILED_impl(IsFromCache(&fromCache
))), 0)))
|| !fromCache || !mCacheEntry ||
9233 NS_FAILED(mCacheEntry->GetCacheEntryId(aCacheEntryId))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCacheEntry->GetCacheEntryId
(aCacheEntryId))), 0)))
) {
9234 return NS_ERROR_NOT_AVAILABLE;
9235 }
9236
9237 return NS_OK;
9238}
9239
9240NS_IMETHODIMPnsresult
9241nsHttpChannel::GetCacheTokenFetchCount(uint32_t* _retval) {
9242 NS_ENSURE_ARG_POINTER(_retval)do { if ((__builtin_expect(!!(!(_retval)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_retval" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9242); return NS_ERROR_INVALID_POINTER; } } while (false)
;
9243 nsCOMPtr<nsICacheEntry> cacheEntry =
9244 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
9245 if (!cacheEntry) {
9246 return NS_ERROR_NOT_AVAILABLE;
9247 }
9248
9249 return cacheEntry->GetFetchCount(_retval);
9250}
9251
9252NS_IMETHODIMPnsresult
9253nsHttpChannel::GetCacheTokenExpirationTime(uint32_t* _retval) {
9254 NS_ENSURE_ARG_POINTER(_retval)do { if ((__builtin_expect(!!(!(_retval)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_retval" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9254); return NS_ERROR_INVALID_POINTER; } } while (false)
;
9255 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
9256
9257 return mCacheEntry->GetExpirationTime(_retval);
9258}
9259
9260NS_IMETHODIMPnsresult
9261nsHttpChannel::SetAllowStaleCacheContent(bool aAllowStaleCacheContent) {
9262 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)
9263 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)
;
9264 StoreAllowStaleCacheContent(aAllowStaleCacheContent);
9265 return NS_OK;
9266}
9267NS_IMETHODIMPnsresult
9268nsHttpChannel::GetAllowStaleCacheContent(bool* aAllowStaleCacheContent) {
9269 NS_ENSURE_ARG(aAllowStaleCacheContent)do { if ((__builtin_expect(!!(!(aAllowStaleCacheContent)), 0)
)) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowStaleCacheContent"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9269); return NS_ERROR_INVALID_ARG; } } while (false)
;
9270 *aAllowStaleCacheContent = LoadAllowStaleCacheContent();
9271 return NS_OK;
9272}
9273
9274NS_IMETHODIMPnsresult
9275nsHttpChannel::SetForceValidateCacheContent(bool aForceValidateCacheContent) {
9276 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)
9277 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)
;
9278 StoreForceValidateCacheContent(aForceValidateCacheContent);
9279 return NS_OK;
9280}
9281NS_IMETHODIMPnsresult
9282nsHttpChannel::GetForceValidateCacheContent(bool* aForceValidateCacheContent) {
9283 NS_ENSURE_ARG(aForceValidateCacheContent)do { if ((__builtin_expect(!!(!(aForceValidateCacheContent)),
0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aForceValidateCacheContent"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9283); return NS_ERROR_INVALID_ARG; } } while (false)
;
9284 *aForceValidateCacheContent = LoadForceValidateCacheContent();
9285 return NS_OK;
9286}
9287
9288NS_IMETHODIMPnsresult
9289nsHttpChannel::SetPreferCacheLoadOverBypass(bool aPreferCacheLoadOverBypass) {
9290 StorePreferCacheLoadOverBypass(aPreferCacheLoadOverBypass);
9291 return NS_OK;
9292}
9293NS_IMETHODIMPnsresult
9294nsHttpChannel::GetPreferCacheLoadOverBypass(bool* aPreferCacheLoadOverBypass) {
9295 NS_ENSURE_ARG(aPreferCacheLoadOverBypass)do { if ((__builtin_expect(!!(!(aPreferCacheLoadOverBypass)),
0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPreferCacheLoadOverBypass"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9295); return NS_ERROR_INVALID_ARG; } } while (false)
;
9296 *aPreferCacheLoadOverBypass = LoadPreferCacheLoadOverBypass();
9297 return NS_OK;
9298}
9299
9300NS_IMETHODIMPnsresult
9301nsHttpChannel::PreferAlternativeDataType(
9302 const nsACString& aType, const nsACString& aContentType,
9303 PreferredAlternativeDataDeliveryType aDeliverAltData) {
9304 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9304); 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("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9304, 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9304); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9304); return NS_ERROR_IN_PROGRESS; } } while (false); do {
if ((__builtin_expect(!!(!(!LoadWasOpened())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadWasOpened()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9304); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
9305 mPreferredCachedAltDataTypes.AppendElement(PreferredAlternativeDataTypeParams(
9306 nsCString(aType), nsCString(aContentType), aDeliverAltData));
9307 return NS_OK;
9308}
9309
9310const nsTArray<PreferredAlternativeDataTypeParams>&
9311nsHttpChannel::PreferredAlternativeDataTypes() {
9312 return mPreferredCachedAltDataTypes;
9313}
9314
9315NS_IMETHODIMPnsresult
9316nsHttpChannel::GetAlternativeDataType(nsACString& aType) {
9317 // must be called during or after OnStartRequest
9318 if (!LoadAfterOnStartRequestBegun()) {
9319 return NS_ERROR_NOT_AVAILABLE;
9320 }
9321 aType = mAvailableCachedAltDataType;
9322 return NS_OK;
9323}
9324
9325NS_IMETHODIMPnsresult
9326nsHttpChannel::OpenAlternativeOutputStream(const nsACString& type,
9327 int64_t predictedSize,
9328 nsIAsyncOutputStream** _retval) {
9329 // OnStopRequest will clear mCacheEntry, but we may use mAltDataCacheEntry
9330 // if the consumer called PreferAlternativeDataType()
9331 nsCOMPtr<nsICacheEntry> cacheEntry =
9332 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
9333 if (!cacheEntry) {
9334 return NS_ERROR_NOT_AVAILABLE;
9335 }
9336 nsresult rv =
9337 cacheEntry->OpenAlternativeOutputStream(type, predictedSize, _retval);
9338 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9339 // Clear this metadata flag in case it exists.
9340 // The caller of this method may set it again.
9341 cacheEntry->SetMetaDataElement("alt-data-from-child", nullptr);
9342 }
9343 return rv;
9344}
9345
9346NS_IMETHODIMPnsresult
9347nsHttpChannel::GetOriginalInputStream(nsIInputStreamReceiver* aReceiver) {
9348 if (aReceiver == nullptr) {
9349 return NS_ERROR_INVALID_ARG;
9350 }
9351 nsCOMPtr<nsIInputStream> inputStream;
9352
9353 nsCOMPtr<nsICacheEntry> cacheEntry =
9354 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
9355 if (cacheEntry) {
9356 cacheEntry->OpenInputStream(0, getter_AddRefs(inputStream));
9357 }
9358 aReceiver->OnInputStreamReady(inputStream);
9359 return NS_OK;
9360}
9361
9362NS_IMETHODIMPnsresult
9363nsHttpChannel::GetAlternativeDataInputStream(nsIInputStream** aInputStream) {
9364 NS_ENSURE_ARG_POINTER(aInputStream)do { if ((__builtin_expect(!!(!(aInputStream)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aInputStream" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9364); return NS_ERROR_INVALID_POINTER; } } while (false)
;
9365
9366 *aInputStream = nullptr;
9367
9368 nsCOMPtr<nsICacheEntry> cacheEntry =
9369 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
9370 if (!mAvailableCachedAltDataType.IsEmpty() && cacheEntry) {
9371 nsresult rv = cacheEntry->OpenAlternativeInputStream(
9372 mAvailableCachedAltDataType, aInputStream);
9373 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9373); return rv; } } while (false)
;
9374 }
9375 return NS_OK;
9376}
9377
9378//-----------------------------------------------------------------------------
9379// nsHttpChannel::nsICachingChannel
9380//-----------------------------------------------------------------------------
9381
9382NS_IMETHODIMPnsresult
9383nsHttpChannel::IsRacing(bool* aIsRacing) {
9384 if (!LoadAfterOnStartRequestBegun()) {
9385 return NS_ERROR_NOT_AVAILABLE;
9386 }
9387 *aIsRacing = mRaceCacheWithNetwork;
9388 return NS_OK;
9389}
9390
9391NS_IMETHODIMPnsresult
9392nsHttpChannel::GetCacheToken(nsISupports** token) {
9393 NS_ENSURE_ARG_POINTER(token)do { if ((__builtin_expect(!!(!(token)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "token" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9393); return NS_ERROR_INVALID_POINTER; } } while (false)
;
9394 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
9395 return CallQueryInterface(mCacheEntry, token);
9396}
9397
9398NS_IMETHODIMPnsresult
9399nsHttpChannel::SetCacheToken(nsISupports* token) {
9400 return NS_ERROR_NOT_IMPLEMENTED;
9401}
9402
9403NS_IMETHODIMPnsresult
9404nsHttpChannel::GetCacheKey(uint32_t* key) {
9405 NS_ENSURE_ARG_POINTER(key)do { if ((__builtin_expect(!!(!(key)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "key" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9405); return NS_ERROR_INVALID_POINTER; } } while (false)
;
9406
9407 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)
;
9408
9409 *key = mPostID;
9410 return NS_OK;
9411}
9412
9413NS_IMETHODIMPnsresult
9414nsHttpChannel::SetCacheKey(uint32_t key) {
9415 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)
;
9416
9417 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9417); 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("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9417, 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9417); } } 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9417); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()"
")"); do { *((volatile int*)__null) = 9417; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
9418
9419 mPostID = key;
9420 return NS_OK;
9421}
9422
9423NS_IMETHODIMPnsresult
9424nsHttpChannel::GetCacheOnlyMetadata(bool* aOnlyMetadata) {
9425 NS_ENSURE_ARG(aOnlyMetadata)do { if ((__builtin_expect(!!(!(aOnlyMetadata)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOnlyMetadata" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9425); return NS_ERROR_INVALID_ARG; } } while (false)
;
9426 *aOnlyMetadata = LoadCacheOnlyMetadata();
9427 return NS_OK;
9428}
9429
9430NS_IMETHODIMPnsresult
9431nsHttpChannel::SetCacheOnlyMetadata(bool aOnlyMetadata) {
9432 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)
9433 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)
;
9434
9435 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9435); 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("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9435, 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9435); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9435); return NS_ERROR_IN_PROGRESS; } } while (false); do {
if ((__builtin_expect(!!(!(!LoadWasOpened())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadWasOpened()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9435); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
9436
9437 StoreCacheOnlyMetadata(aOnlyMetadata);
9438 if (aOnlyMetadata) {
9439 mLoadFlags |= LOAD_ONLY_IF_MODIFIED;
9440 }
9441
9442 return NS_OK;
9443}
9444
9445NS_IMETHODIMPnsresult
9446nsHttpChannel::GetPin(bool* aPin) {
9447 NS_ENSURE_ARG(aPin)do { if ((__builtin_expect(!!(!(aPin)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPin" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9447); return NS_ERROR_INVALID_ARG; } } while (false)
;
9448 *aPin = LoadPinCacheContent();
9449 return NS_OK;
9450}
9451
9452NS_IMETHODIMPnsresult
9453nsHttpChannel::SetPin(bool aPin) {
9454 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)
;
9455
9456 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9456); 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("/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9456, 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9456); } } 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()"
")"); do { *((volatile int*)__null) = 9456; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
9457
9458 StorePinCacheContent(aPin);
9459 return NS_OK;
9460}
9461
9462NS_IMETHODIMPnsresult
9463nsHttpChannel::ForceCacheEntryValidFor(uint32_t aSecondsToTheFuture) {
9464 if (!mCacheEntry) {
9465 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
9466 ("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)
9467 "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)
9468 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
9469 } else {
9470 mCacheEntry->ForceValidFor(aSecondsToTheFuture);
9471
9472 nsAutoCString key;
9473 mCacheEntry->GetKey(key);
9474
9475 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
9476 ("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)
9477 "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)
9478 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)
;
9479 }
9480
9481 return NS_OK;
9482}
9483
9484//-----------------------------------------------------------------------------
9485// nsHttpChannel::nsIResumableChannel
9486//-----------------------------------------------------------------------------
9487
9488NS_IMETHODIMPnsresult
9489nsHttpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) {
9490 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)
9491 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)
;
9492 mEntityID = aEntityID;
9493 mStartPos = aStartPos;
9494 StoreResuming(true);
9495 return NS_OK;
9496}
9497
9498nsresult nsHttpChannel::DoAuthRetry(
9499 HttpTransactionShell* aTransWithStickyConn,
9500 const std::function<nsresult(nsHttpChannel*, nsresult)>&
9501 aContinueOnStopRequestFunc) {
9502 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)
9503 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)
;
9504
9505 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mTransaction"
") (" "should not have a transaction" ")"); do { *((volatile
int*)__null) = 9505; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9506
9507 // Note that we don't have to toggle |IsPending| anymore. See the reasons
9508 // below.
9509 // 1. We can't suspend the channel during "http-on-modify-request"
9510 // when |IsPending| is false.
9511 // 2. We don't check |IsPending| in SetRequestHeader now.
9512
9513 // Reset RequestObserversCalled because we've probably called the request
9514 // observers once already.
9515 StoreRequestObserversCalled(false);
9516
9517 // fetch cookies, and add them to the request header.
9518 // the server response could have included cookies that must be sent with
9519 // this authentication attempt (bug 84794).
9520 // TODO: save cookies from auth response and send them here (bug 572151).
9521 AddCookiesToRequest();
9522
9523 // notify "http-on-modify-request" observers
9524 CallOnModifyRequestObservers();
9525
9526 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
9527 return CallOrWaitForResume(
9528 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
9529 return self->ContinueDoAuthRetry(trans, aContinueOnStopRequestFunc);
9530 });
9531}
9532
9533nsresult nsHttpChannel::ContinueDoAuthRetry(
9534 HttpTransactionShell* aTransWithStickyConn,
9535 const std::function<nsresult(nsHttpChannel*, nsresult)>&
9536 aContinueOnStopRequestFunc) {
9537 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)
;
9538 StoreIsPending(true);
9539
9540 // get rid of the old response headers
9541 mResponseHead = nullptr;
9542
9543 // rewind the upload stream
9544 if (mUploadStream) {
9545 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
9546 nsresult rv = NS_ERROR_NO_INTERFACE;
9547 if (seekable) {
9548 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
9549 }
9550
9551 // This should not normally happen, but it's possible that big memory
9552 // blobs originating in the other process can't be rewinded.
9553 // In that case we just fail the request, otherwise the content length
9554 // will not match and this load will never complete.
9555 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9555); return rv; } } while (false)
;
9556 }
9557
9558 // always set sticky connection flag
9559 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
9560 // and when needed, allow restart regardless the sticky flag
9561 if (LoadAuthConnectionRestartable()) {
9562 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)
;
9563 mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
9564 StoreAuthConnectionRestartable(false);
9565 } else {
9566 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)
;
9567 mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
9568 }
9569
9570 // notify "http-on-before-connect" observers
9571 gHttpHandler->OnBeforeConnect(this);
9572
9573 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
9574 return CallOrWaitForResume(
9575 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
9576 nsresult rv = self->DoConnect(trans);
9577 return aContinueOnStopRequestFunc(self, rv);
9578 });
9579}
9580
9581//-----------------------------------------------------------------------------
9582// nsHttpChannel::nsIAsyncVerifyRedirectCallback
9583//-----------------------------------------------------------------------------
9584
9585nsresult nsHttpChannel::WaitForRedirectCallback() {
9586 nsresult rv;
9587 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)
;
9588
9589 if (mTransactionPump) {
9590 rv = mTransactionPump->Suspend();
9591 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9591); return rv; } } while (false)
;
9592 }
9593 if (mCachePump) {
9594 rv = mCachePump->Suspend();
9595 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && mTransactionPump) {
9596#ifdef DEBUG1
9597 nsresult resume =
9598#endif
9599 mTransactionPump->Resume();
9600 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9600); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(resume)), 1)))"
") (" "Failed to resume transaction pump" ")"); do { *((volatile
int*)__null) = 9600; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9601 }
9602 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9602); return rv; } } while (false)
;
9603 }
9604
9605 StoreWaitingForRedirectCallback(true);
9606 return NS_OK;
9607}
9608
9609NS_IMETHODIMPnsresult
9610nsHttpChannel::OnRedirectVerifyCallback(nsresult result) {
9611 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
9612 ("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)
9613 "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)
9614 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)
9615 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)
;
9616 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() ?!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { *((volatile int*)__null) = 9617; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9617 "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() ?!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { *((volatile int*)__null) = 9617; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9618 StoreWaitingForRedirectCallback(false);
9619
9620 if (mCanceled && NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) result = NS_BINDING_ABORTED;
9621
9622 for (uint32_t i = mRedirectFuncStack.Length(); i > 0;) {
9623 --i;
9624 // Pop the last function pushed to the stack
9625 nsContinueRedirectionFunc func = mRedirectFuncStack.PopLastElement();
9626
9627 // Call it with the result we got from the callback or the deeper
9628 // function call.
9629 result = (this->*func)(result);
9630
9631 // If a new function has been pushed to the stack and placed us in the
9632 // waiting state, we need to break the chain and wait for the callback
9633 // again.
9634 if (LoadWaitingForRedirectCallback()) break;
9635 }
9636
9637 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
9638 // First, cancel this channel if we are in failure state to set mStatus
9639 // and let it be propagated to pumps.
9640 Cancel(result);
9641 }
9642
9643 if (!LoadWaitingForRedirectCallback()) {
9644 // We are not waiting for the callback. At this moment we must release
9645 // reference to the redirect target channel, otherwise we may leak.
9646 // However, if we are redirecting due to auth retries, we open the
9647 // redirected channel after OnStopRequest. In that case we should not
9648 // release the reference
9649 if (!StaticPrefs::network_auth_use_redirect_for_retries() ||
9650 !mAuthRetryPending) {
9651 mRedirectChannel = nullptr;
9652 }
9653 }
9654
9655 // We always resume the pumps here. If all functions on stack have been
9656 // called we need OnStopRequest to be triggered, and if we broke out of the
9657 // loop above (and are thus waiting for a new callback) the suspension
9658 // count must be balanced in the pumps.
9659 if (mTransactionPump) mTransactionPump->Resume();
9660 if (mCachePump) mCachePump->Resume();
9661
9662 return result;
9663}
9664
9665void nsHttpChannel::PushRedirectAsyncFunc(nsContinueRedirectionFunc func) {
9666 mRedirectFuncStack.AppendElement(func);
9667}
9668
9669void nsHttpChannel::PopRedirectAsyncFunc(nsContinueRedirectionFunc func) {
9670 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!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { *((volatile int*)__null) = 9671; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9671 "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!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { *((volatile int*)__null) = 9671; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9672
9673 mRedirectFuncStack.RemoveLastElement();
9674}
9675
9676//-----------------------------------------------------------------------------
9677// nsIDNSListener functions
9678//-----------------------------------------------------------------------------
9679
9680NS_IMETHODIMPnsresult
9681nsHttpChannel::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
9682 nsresult status) {
9683 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { *(
(volatile int*)__null) = 9683; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9684
9685 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
9686 ("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)
9687 "%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)
9688 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)
9689 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)
9690 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)
;
9691
9692 // Unset DNS cache refresh if it was requested,
9693 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
9694 mCaps &= ~NS_HTTP_REFRESH_DNS(1 << 3);
9695 if (mTransaction) {
9696 mTransaction->SetDNSWasRefreshed();
9697 }
9698 }
9699
9700 if (!mDNSBlockingPromise.IsEmpty()) {
9701 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
9702 nsCOMPtr<nsIDNSRecord> record(rec);
9703 mDNSBlockingPromise.Resolve(record, __func__);
9704 } else {
9705 mDNSBlockingPromise.Reject(status, __func__);
9706 }
9707 }
9708
9709 return NS_OK;
9710}
9711
9712void nsHttpChannel::OnHTTPSRRAvailable(nsIDNSHTTPSSVCRecord* aRecord) {
9713 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { *(
(volatile int*)__null) = 9713; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9714
9715 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)
9716 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)
;
9717
9718 if (mHTTPSSVCRecord) {
9719 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!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"OnHTTPSRRAvailable called twice!" ")"); do { *((volatile int
*)__null) = 9719; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9720 return;
9721 }
9722
9723 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
9724 mHTTPSSVCRecord.emplace(std::move(record));
9725 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& httprr = mHTTPSSVCRecord.ref();
9726
9727 if (LoadWaitHTTPSSVCRecord()) {
9728 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\")"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mURI->SchemeIs(\"http\")"
")"); do { *((volatile int*)__null) = 9728; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9729
9730 StoreWaitHTTPSSVCRecord(false);
9731 nsresult rv = ContinueOnBeforeConnect(!!httprr, mStatus, !!httprr);
9732 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9733 CloseCacheEntry(false);
9734 Unused << AsyncAbort(rv);
9735 }
9736 } else {
9737 // This channel is not canceled and the transaction is not created.
9738 if (httprr && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mTransaction &&
9739 (mFirstResponseSource != RESPONSE_FROM_CACHE)) {
9740 bool hasIPAddress = false;
9741 Unused << httprr->GetHasIPAddresses(&hasIPAddress);
9742 Telemetry::Accumulate(Telemetry::DNS_HTTPSSVC_RECORD_RECEIVING_STAGE,
9743 hasIPAddress
9744 ? HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_0
9745 : HTTPSSVC_WITHOUT_IPHINT_RECEIVED_STAGE_0);
9746 StoreHTTPSSVCTelemetryReported(true);
9747 }
9748 }
9749}
9750
9751//-----------------------------------------------------------------------------
9752// nsHttpChannel internal functions
9753//-----------------------------------------------------------------------------
9754
9755// Creates an URI to the given location using current URI for base and charset
9756nsresult nsHttpChannel::CreateNewURI(const char* loc, nsIURI** newURI) {
9757 nsCOMPtr<nsIIOService> ioService;
9758 nsresult rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
9759 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
9760
9761 return ioService->NewURI(nsDependentCString(loc), nullptr, mURI, newURI);
9762}
9763
9764void nsHttpChannel::MaybeInvalidateCacheEntryForSubsequentGet() {
9765 // See RFC 2616 section 5.1.1. These are considered valid
9766 // methods which DO NOT invalidate cache-entries for the
9767 // referred resource. POST, PUT and DELETE as well as any
9768 // other method not listed here will potentially invalidate
9769 // any cached copy of the resource
9770 if (mRequestHead.IsGet() || mRequestHead.IsOptions() ||
9771 mRequestHead.IsHead() || mRequestHead.IsTrace() ||
9772 mRequestHead.IsConnect()) {
9773 return;
9774 }
9775
9776 // Invalidate the request-uri.
9777 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
9778 nsAutoCString key;
9779 mURI->GetAsciiSpec(key);
9780 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)
9781 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)
;
9782 }
9783
9784 DoInvalidateCacheEntry(mURI);
9785
9786 // Invalidate Location-header if set
9787 nsAutoCString location;
9788 Unused << mResponseHead->GetHeader(nsHttp::Location, location);
9789 if (!location.IsEmpty()) {
9790 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)
;
9791 InvalidateCacheEntryForLocation(location.get());
9792 }
9793
9794 // Invalidate Content-Location-header if set
9795 Unused << mResponseHead->GetHeader(nsHttp::Content_Location, location);
9796 if (!location.IsEmpty()) {
9797 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)
;
9798 InvalidateCacheEntryForLocation(location.get());
9799 }
9800}
9801
9802void nsHttpChannel::InvalidateCacheEntryForLocation(const char* location) {
9803 nsAutoCString tmpCacheKey, tmpSpec;
9804 nsCOMPtr<nsIURI> resultingURI;
9805 nsresult rv = CreateNewURI(location, getter_AddRefs(resultingURI));
9806 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && HostPartIsTheSame(resultingURI)) {
9807 DoInvalidateCacheEntry(resultingURI);
9808 } else {
9809 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)
;
9810 }
9811}
9812
9813void nsHttpChannel::DoInvalidateCacheEntry(nsIURI* aURI) {
9814 // NOTE:
9815 // Following comments 24,32 and 33 in bug #327765, we only care about
9816 // the cache in the protocol-handler.
9817 // The logic below deviates from the original logic in OpenCacheEntry on
9818 // one point by using only READ_ONLY access-policy. I think this is safe.
9819
9820 nsresult rv;
9821
9822 nsAutoCString key;
9823 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
9824 aURI->GetAsciiSpec(key);
9825 }
9826
9827 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)
;
9828
9829 nsCOMPtr<nsICacheStorageService> cacheStorageService(
9830 components::CacheStorage::Service());
9831 rv = cacheStorageService ? NS_OK : NS_ERROR_FAILURE;
9832
9833 nsCOMPtr<nsICacheStorage> cacheStorage;
9834 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9835 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
9836 rv = cacheStorageService->DiskCacheStorage(info,
9837 getter_AddRefs(cacheStorage));
9838 }
9839
9840 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9841 rv = cacheStorage->AsyncDoomURI(aURI, ""_ns, nullptr);
9842 }
9843
9844 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)
9845 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)
;
9846}
9847
9848void nsHttpChannel::AsyncOnExamineCachedResponse() {
9849 gHttpHandler->OnExamineCachedResponse(this);
9850}
9851
9852void nsHttpChannel::UpdateAggregateCallbacks() {
9853 if (!mTransaction) {
9854 return;
9855 }
9856 nsCOMPtr<nsIInterfaceRequestor> callbacks;
9857 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
9858 GetCurrentSerialEventTarget(),
9859 getter_AddRefs(callbacks));
9860 mTransaction->SetSecurityCallbacks(callbacks);
9861}
9862
9863NS_IMETHODIMPnsresult
9864nsHttpChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
9865 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9865); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { *((volatile int*)__null) = 9865
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
9866
9867 nsresult rv = HttpBaseChannel::SetLoadGroup(aLoadGroup);
9868 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9869 UpdateAggregateCallbacks();
9870 }
9871 return rv;
9872}
9873
9874NS_IMETHODIMPnsresult
9875nsHttpChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
9876 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." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { *((volatile int*)__null) = 9876
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
9877
9878 nsresult rv = HttpBaseChannel::SetNotificationCallbacks(aCallbacks);
9879 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9880 UpdateAggregateCallbacks();
9881 }
9882 return rv;
9883}
9884
9885bool nsHttpChannel::AwaitingCacheCallbacks() {
9886 return LoadWaitForCacheEntry() != 0;
9887}
9888
9889void nsHttpChannel::SetPushedStreamTransactionAndId(
9890 HttpTransactionShell* aTransWithPushedStream, uint32_t aPushedStreamId) {
9891 MOZ_ASSERT(!mTransWithPushedStream)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mTransWithPushedStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mTransWithPushedStream))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mTransWithPushedStream"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9891); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mTransWithPushedStream"
")"); do { *((volatile int*)__null) = 9891; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9892 LOG(("nsHttpChannel::SetPushedStreamTransaction [this=%p] trans=%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::SetPushedStreamTransaction [this=%p] trans=%p"
, this, aTransWithPushedStream); } } while (0)
9893 aTransWithPushedStream))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetPushedStreamTransaction [this=%p] trans=%p"
, this, aTransWithPushedStream); } } while (0)
;
9894
9895 mTransWithPushedStream = aTransWithPushedStream;
9896 mPushedStreamId = aPushedStreamId;
9897}
9898
9899nsresult nsHttpChannel::OnPush(uint32_t aPushedStreamId, const nsACString& aUrl,
9900 const nsACString& aRequestString,
9901 HttpTransactionShell* aTransaction) {
9902 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 9902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9903 MOZ_ASSERT(aTransaction)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTransaction)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTransaction))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aTransaction", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTransaction"
")"); do { *((volatile int*)__null) = 9903; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9904 LOG(("nsHttpChannel::OnPush [this=%p, trans=%p]\n", this, aTransaction))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPush [this=%p, trans=%p]\n", this, aTransaction
); } } while (0)
;
9905
9906 MOZ_ASSERT(mCaps & NS_HTTP_ONPUSH_LISTENER)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCaps & (1 << 9))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCaps & (1 << 9)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mCaps & (1 << 9)"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCaps & (1 << 9)"
")"); do { *((volatile int*)__null) = 9906; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9907 nsCOMPtr<nsIHttpPushListener> pushListener;
9908 NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
9909 NS_GET_IID(nsIHttpPushListener)(nsIHttpPushListener::COMTypeInfo<nsIHttpPushListener, void
>::kIID)
,
9910 getter_AddRefs(pushListener));
9911
9912 if (!pushListener) {
9913 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPush [this=%p] notification callbacks do not "
"implement nsIHttpPushListener\n", this); } } while (0)
9914 ("nsHttpChannel::OnPush [this=%p] notification callbacks do 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::OnPush [this=%p] notification callbacks do not "
"implement nsIHttpPushListener\n", this); } } while (0)
9915 "implement nsIHttpPushListener\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPush [this=%p] notification callbacks do not "
"implement nsIHttpPushListener\n", this); } } while (0)
9916 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPush [this=%p] notification callbacks do not "
"implement nsIHttpPushListener\n", this); } } while (0)
;
9917 return NS_ERROR_NOT_AVAILABLE;
9918 }
9919
9920 nsCOMPtr<nsIURI> pushResource;
9921 nsresult rv;
9922
9923 // Create a Channel for the Push Resource
9924 rv = NS_NewURI(getter_AddRefs(pushResource), aUrl);
9925 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9926 return NS_ERROR_FAILURE;
9927 }
9928
9929 nsCOMPtr<nsIIOService> ioService;
9930 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9931); return rv; } } while (false)
;
9932
9933 nsCOMPtr<nsIChannel> pushChannel;
9934 rv = NS_NewChannelInternal(getter_AddRefs(pushChannel), pushResource,
9935 mLoadInfo,
9936 nullptr, // PerformanceStorage
9937 nullptr, // aLoadGroup
9938 nullptr, // aCallbacks
9939 nsIRequest::LOAD_NORMAL, ioService);
9940 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9940); return rv; } } while (false)
;
9941
9942 nsCOMPtr<nsIHttpChannel> pushHttpChannel = do_QueryInterface(pushChannel);
9943 MOZ_ASSERT(pushHttpChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pushHttpChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pushHttpChannel))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("pushHttpChannel"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pushHttpChannel"
")"); do { *((volatile int*)__null) = 9943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9944 if (!pushHttpChannel) {
9945 return NS_ERROR_UNEXPECTED;
9946 }
9947
9948 RefPtr<nsHttpChannel> channel;
9949 CallQueryInterface(pushHttpChannel, channel.StartAssignment());
9950 MOZ_ASSERT(channel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(channel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(channel))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("channel", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { *((volatile int*)__null) = 9950; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9951 if (!channel) {
9952 return NS_ERROR_UNEXPECTED;
9953 }
9954
9955 // new channel needs mrqeuesthead and headers from pushedStream
9956 channel->mRequestHead.ParseHeaderSet(aRequestString.BeginReading());
9957 channel->mLoadGroup = mLoadGroup;
9958 channel->mLoadInfo = mLoadInfo;
9959 channel->mCallbacks = mCallbacks;
9960
9961 // Link the trans with pushed stream and the new channel and call listener
9962 channel->SetPushedStreamTransactionAndId(aTransaction, aPushedStreamId);
9963 rv = pushListener->OnPush(this, pushHttpChannel);
9964 return rv;
9965}
9966
9967// static
9968bool nsHttpChannel::IsRedirectStatus(uint32_t status) {
9969 // 305 disabled as a security measure (see bug 187996).
9970 return status == 301 || status == 302 || status == 303 || status == 307 ||
9971 status == 308;
9972}
9973
9974void nsHttpChannel::SetCouldBeSynthesized() {
9975 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9975); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
")"); do { *((volatile int*)__null) = 9975; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9976 StoreResponseCouldBeSynthesized(true);
9977}
9978
9979NS_IMETHODIMPnsresult
9980nsHttpChannel::OnPreflightSucceeded() {
9981 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { *((volatile int
*)__null) = 9981; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9982 StoreIsCorsPreflightDone(1);
9983 mPreflightChannel = nullptr;
9984
9985 return ContinueConnect();
9986}
9987
9988NS_IMETHODIMPnsresult
9989nsHttpChannel::OnPreflightFailed(nsresult aError) {
9990 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?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 9990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { *((volatile int
*)__null) = 9990; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9991 StoreIsCorsPreflightDone(1);
9992 mPreflightChannel = nullptr;
9993
9994 CloseCacheEntry(false);
9995 Unused << AsyncAbort(aError);
9996 return NS_OK;
9997}
9998
9999nsresult nsHttpChannel::CallOrWaitForResume(
10000 const std::function<nsresult(nsHttpChannel*)>& aFunc) {
10001 if (mCanceled) {
10002 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)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))"
")"); do { *((volatile int*)__null) = 10002; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10003 return mStatus;
10004 }
10005
10006 if (mSuspendCount) {
10007 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)
;
10008 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
")"); do { *((volatile int*)__null) = 10008; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10009 mCallOnResume = aFunc;
10010 return NS_OK;
10011 }
10012
10013 return aFunc(this);
10014}
10015
10016// This is loosely based on:
10017// https://fetch.spec.whatwg.org/#serializing-a-request-origin
10018static bool HasNullRequestOrigin(nsHttpChannel* aChannel, nsIURI* aURI,
10019 bool isAddonRequest) {
10020 // Step 1. If request has a redirect-tainted origin, then return "null".
10021 if (aChannel->HasRedirectTaintedOrigin()) {
10022 if (StaticPrefs::network_http_origin_redirectTainted()) {
10023 return true;
10024 }
10025 }
10026
10027 // Non-standard: Only allow HTTP and HTTPS origins.
10028 if (!ReferrerInfo::IsReferrerSchemeAllowed(aURI)) {
10029 // And moz-extension: for add-on initiated requests.
10030 if (!aURI->SchemeIs("moz-extension") || !isAddonRequest) {
10031 return true;
10032 }
10033 }
10034
10035 // Non-standard: Hide onion URLs.
10036 if (StaticPrefs::network_http_referer_hideOnionSource()) {
10037 nsAutoCString host;
10038 if (NS_SUCCEEDED(aURI->GetAsciiHost(host))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aURI->GetAsciiHost
(host))), 1)))
&&
10039 StringEndsWith(host, ".onion"_ns)) {
10040 return ReferrerInfo::IsCrossOriginRequest(aChannel);
10041 }
10042 }
10043
10044 // Step 2. Return request’s origin, serialized.
10045 return false;
10046}
10047
10048// Step 8.12. of HTTP-network-or-cache fetch
10049//
10050// https://fetch.spec.whatwg.org/#append-a-request-origin-header
10051void nsHttpChannel::SetOriginHeader() {
10052 auto* triggeringPrincipal =
10053 BasePrincipal::Cast(mLoadInfo->TriggeringPrincipal());
10054
10055 if (triggeringPrincipal->IsSystemPrincipal()) {
10056 // We can't infer an Origin header from the system principal,
10057 // this means system requests use whatever Origin header was specified.
10058 return;
10059 }
10060 bool isAddonRequest = triggeringPrincipal->AddonPolicy() ||
10061 triggeringPrincipal->ContentScriptAddonPolicy();
10062
10063 // Non-standard: Handle already existing Origin header.
10064 nsAutoCString existingHeader;
10065 Unused << mRequestHead.GetHeader(nsHttp::Origin, existingHeader);
10066 if (!existingHeader.IsEmpty()) {
10067 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)
;
10068 auto const shouldNullifyOriginHeader =
10069 [&existingHeader, isAddonRequest](nsHttpChannel* aChannel) {
10070 nsCOMPtr<nsIURI> uri;
10071 nsresult rv = NS_NewURI(getter_AddRefs(uri), existingHeader);
10072 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10073 return false;
10074 }
10075
10076 if (HasNullRequestOrigin(aChannel, uri, isAddonRequest)) {
10077 return true;
10078 }
10079
10080 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
10081 if (info->GetTainting() == mozilla::LoadTainting::CORS) {
10082 return false;
10083 }
10084
10085 return ReferrerInfo::ShouldSetNullOriginHeader(aChannel, uri);
10086 };
10087
10088 if (!existingHeader.EqualsLiteral("null") &&
10089 shouldNullifyOriginHeader(this)) {
10090 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)
;
10091 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Origin, "null"_ns, false ))),
1)))), 1))) { } else { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10092); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { *((volatile int*)__null) = 10092; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10092 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 { static_assert( mozilla::detail::
AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10092); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { *((volatile int*)__null) = 10092; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10093 }
10094 return;
10095 }
10096
10097 if (StaticPrefs::network_http_sendOriginHeader() == 0) {
10098 // Custom user setting: 0 means never send Origin header.
10099 return;
10100 }
10101
10102 // Step 1. Let serializedOrigin be the result of byte-serializing a request
10103 // origin with request.
10104 nsAutoCString serializedOrigin;
10105 nsCOMPtr<nsIURI> uri;
10106 {
10107 if (NS_FAILED(triggeringPrincipal->GetURI(getter_AddRefs(uri)))((bool)(__builtin_expect(!!(NS_FAILED_impl(triggeringPrincipal
->GetURI(getter_AddRefs(uri)))), 0)))
) {
10108 return;
10109 }
10110
10111 if (!uri) {
10112 if (isAddonRequest) {
10113 // For add-on compatibility prefer sending no header at all
10114 // instead of `Origin: null`.
10115 return;
10116 }
10117
10118 // Otherwise use "null" when the triggeringPrincipal's URI is nullptr.
10119 serializedOrigin.AssignLiteral("null");
10120 } else if (HasNullRequestOrigin(this, uri, isAddonRequest)) {
10121 serializedOrigin.AssignLiteral("null");
10122 } else {
10123 nsContentUtils::GetWebExposedOriginSerialization(uri, serializedOrigin);
10124 }
10125 }
10126
10127 // Step 2. If request’s response tainting is "cors" or request’s mode is
10128 // "websocket", then append (`Origin`, serializedOrigin) to request’s header
10129 // list.
10130 //
10131 // Note: We don't handle "websocket" here (yet?).
10132 if (mLoadInfo->GetTainting() == mozilla::LoadTainting::CORS) {
10133 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 { static_assert( mozilla::detail
::AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10134); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { *((volatile int*)__null) = 10134; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10134 false /* merge */))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false
))), 1)))), 1))) { } else { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10134); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { *((volatile int*)__null) = 10134; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10135 return;
10136 }
10137
10138 // Step 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then:
10139 if (mRequestHead.IsGet() || mRequestHead.IsHead()) {
10140 return;
10141 }
10142
10143 if (!serializedOrigin.EqualsLiteral("null")) {
10144 // Step 3.1. (Implemented by ReferrerInfo::ShouldSetNullOriginHeader)
10145 if (ReferrerInfo::ShouldSetNullOriginHeader(this, uri)) {
10146 serializedOrigin.AssignLiteral("null");
10147 } else if (StaticPrefs::network_http_sendOriginHeader() == 1) {
10148 // Non-standard: Restrict Origin to same-origin loads if requested by user
10149 nsAutoCString currentOrigin;
10150 nsContentUtils::GetWebExposedOriginSerialization(mURI, currentOrigin);
10151 if (!serializedOrigin.EqualsIgnoreCase(currentOrigin.get())) {
10152 // Origin header suppressed by user setting.
10153 serializedOrigin.AssignLiteral("null");
10154 }
10155 }
10156 }
10157
10158 // Step 3.2. Append (`Origin`, serializedOrigin) to request’s header list.
10159 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 { static_assert( mozilla::detail
::AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10160); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { *((volatile int*)__null) = 10160; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10160 false /* merge */))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false
))), 1)))), 1))) { } else { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10160); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { *((volatile int*)__null) = 10160; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10161}
10162
10163void nsHttpChannel::SetDoNotTrack() {
10164 /**
10165 * 'DoNotTrack' header should be added if 'privacy.donottrackheader.enabled'
10166 * is true or tracking protection is enabled. See bug 1258033.
10167 */
10168 nsCOMPtr<nsILoadContext> loadContext;
10169 NS_QueryNotificationCallbacks(this, loadContext);
10170
10171 if ((loadContext && loadContext->UseTrackingProtection()) ||
10172 StaticPrefs::privacy_donottrackheader_enabled()) {
10173 DebugOnly<nsresult> rv =
10174 mRequestHead.SetHeader(nsHttp::DoNotTrack, "1"_ns, false);
10175 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)))", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 10175; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10176 }
10177}
10178
10179void nsHttpChannel::SetGlobalPrivacyControl() {
10180 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { *((volatile
int*)__null) = 10180; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10181
10182 if (StaticPrefs::privacy_globalprivacycontrol_functionality_enabled() &&
10183 (StaticPrefs::privacy_globalprivacycontrol_enabled() ||
10184 (StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled() &&
10185 NS_UsePrivateBrowsing(this)))) {
10186 // Send the header with a value of 1 to indicate opting-out
10187 DebugOnly<nsresult> rv =
10188 mRequestHead.SetHeader(nsHttp::GlobalPrivacyControl, "1"_ns, false);
10189 }
10190}
10191
10192void nsHttpChannel::ReportRcwnStats(bool isFromNet) {
10193 if (!StaticPrefs::network_http_rcwn_enabled()) {
10194 return;
10195 }
10196
10197 if (isFromNet) {
10198 if (mRaceCacheWithNetwork) {
10199 gIOService->IncrementNetWonRequestNumber();
10200 Telemetry::Accumulate(
10201 Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_RACE_NETWORK_WIN,
10202 mTransferSize);
10203 if (mRaceDelay) {
10204 AccumulateCategorical(
10205 Telemetry::LABELS_NETWORK_RACE_CACHE_WITH_NETWORK_USAGE_2::
10206 NetworkDelayedRace);
10207 } else {
10208 AccumulateCategorical(
10209 Telemetry::LABELS_NETWORK_RACE_CACHE_WITH_NETWORK_USAGE_2::
10210 NetworkRace);
10211 }
10212 } else {
10213 Telemetry::Accumulate(Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_NOT_RACE,
10214 mTransferSize);
10215 AccumulateCategorical(
10216 Telemetry::LABELS_NETWORK_RACE_CACHE_WITH_NETWORK_USAGE_2::
10217 NetworkNoRace);
10218 }
10219 } else {
10220 if (mRaceCacheWithNetwork || mRaceDelay) {
10221 gIOService->IncrementCacheWonRequestNumber();
10222 Telemetry::Accumulate(
10223 Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_RACE_CACHE_WIN,
10224 mTransferSize);
10225 if (mRaceDelay) {
10226 AccumulateCategorical(
10227 Telemetry::LABELS_NETWORK_RACE_CACHE_WITH_NETWORK_USAGE_2::
10228 CacheDelayedRace);
10229 } else {
10230 AccumulateCategorical(
10231 Telemetry::LABELS_NETWORK_RACE_CACHE_WITH_NETWORK_USAGE_2::
10232 CacheRace);
10233 }
10234 } else {
10235 Telemetry::Accumulate(Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_NOT_RACE,
10236 mTransferSize);
10237 AccumulateCategorical(
10238 Telemetry::LABELS_NETWORK_RACE_CACHE_WITH_NETWORK_USAGE_2::
10239 CacheNoRace);
10240 }
10241 }
10242
10243 gIOService->IncrementRequestNumber();
10244}
10245
10246void nsHttpChannel::ReportSystemChannelTelemetry(nsresult status) {
10247 // Use status and httpStatus to determine
10248 // if it was successful, and if we had connectivity / offline in this time
10249 nsAutoCString domain;
10250 mOriginalURI->GetHost(domain);
10251
10252 if (!LoadUsedNetwork()) {
10253 // We're not really interested in any cached requests.
10254 return;
10255 }
10256
10257 if (!StringEndsWith(domain, ".mozilla.org"_ns) &&
10258 !StringEndsWith(domain, ".mozilla.com"_ns)) {
10259 return;
10260 }
10261
10262 auto hasConnectivity = []() -> bool {
10263 if (RefPtr<NetworkConnectivityService> ncs =
10264 NetworkConnectivityService::GetSingleton()) {
10265 nsINetworkConnectivityService::ConnectivityState state;
10266 if (NS_SUCCEEDED(ncs->GetIPv4(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetIPv4(&
state))), 1)))
&&
10267 state == nsINetworkConnectivityService::NOT_AVAILABLE &&
10268 NS_SUCCEEDED(ncs->GetIPv6(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetIPv6(&
state))), 1)))
&&
10269 state == nsINetworkConnectivityService::NOT_AVAILABLE) {
10270 return false;
10271 }
10272 }
10273
10274 return true;
10275 };
10276
10277 nsAutoCString label("ok"_ns);
10278 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
10279 if (mCanceled) {
10280 // The request was cancelled.
10281 label = "cancel"_ns;
10282 } else if (NS_IsOffline()) {
10283 // The error occured while all interfaces are offline
10284 label = "offline"_ns;
10285 } else if (!hasConnectivity()) {
10286 // The error occured while the browser didn't have connectivity
10287 label = "connectivity"_ns;
10288 } else if (status == NS_ERROR_UNKNOWN_HOST) {
10289 // The failure was a DNS error
10290 label = "dns"_ns;
10291 } else if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY21) {
10292 // The error was due to TLS
10293 label = "tls_fail"_ns;
10294 } else if (status == NS_ERROR_NET_RESET) {
10295 label = "reset"_ns;
10296 } else if (status == NS_ERROR_NET_TIMEOUT) {
10297 label = "timeout"_ns;
10298 } else if (status == NS_ERROR_CONNECTION_REFUSED) {
10299 label = "refused"_ns;
10300 } else if (status == NS_ERROR_NET_PARTIAL_TRANSFER) {
10301 label = "partial"_ns;
10302 } else {
10303 // Unspecified error. If this bucket is too big we might add other labels.
10304 label = "other"_ns;
10305 }
10306 } else if (mResponseHead && mResponseHead->Status() / 100 != 2) {
10307 // There was no channel error, but the server responded with a non-2XX
10308 // status code.
10309 label = "http_status";
10310 }
10311
10312 if (StringEndsWith(domain, ".addons.mozilla.org"_ns)) {
10313 mozilla::glean::network::system_channel_addonversion_status.Get(label).Add(
10314 1);
10315 return;
10316 }
10317
10318 if (domain == "addons.mozilla.org") {
10319 mozilla::glean::network::system_channel_addon_status.Get(label).Add(1);
10320 return;
10321 }
10322
10323 if (domain == "aus5.mozilla.org"_ns) {
10324 mozilla::glean::network::system_channel_update_status.Get(label).Add(1);
10325 return;
10326 }
10327
10328 if (domain == "firefox.settings.services.mozilla.com"_ns) {
10329 mozilla::glean::network::system_channel_remote_settings_status.Get(label)
10330 .Add(1);
10331 return;
10332 }
10333
10334 if (domain == "incoming.telemetry.mozilla.com"_ns) {
10335 mozilla::glean::network::system_channel_telemetry_status.Get(label).Add(1);
10336 return;
10337 }
10338
10339 // Not one of the probes we recorded earlier.
10340 mozilla::glean::network::system_channel_other_status.Get(label).Add(1);
10341}
10342
10343NS_IMETHODIMPnsresult
10344nsHttpChannel::Test_delayCacheEntryOpeningBy(int32_t aTimeout) {
10345 LOG(("nsHttpChannel::Test_delayCacheEntryOpeningBy this=%p timeout=%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::Test_delayCacheEntryOpeningBy this=%p timeout=%d"
, this, aTimeout); } } while (0)
10346 aTimeout))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Test_delayCacheEntryOpeningBy this=%p timeout=%d"
, this, aTimeout); } } while (0)
;
10347 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { *((volatile
int*)__null) = 10347; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10348 mRaceCacheWithNetwork = true;
10349 mCacheOpenDelay = aTimeout;
10350 if (mCacheOpenTimer) {
10351 mCacheOpenTimer->SetDelay(aTimeout);
10352 }
10353 return NS_OK;
10354}
10355
10356NS_IMETHODIMPnsresult
10357nsHttpChannel::Test_triggerDelayedOpenCacheEntry() {
10358 LOG(("nsHttpChannel::Test_triggerDelayedOpenCacheEntry 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::Test_triggerDelayedOpenCacheEntry this=%p",
this); } } while (0)
;
10359 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { *((volatile
int*)__null) = 10359; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10360 nsresult rv;
10361 if (!mCacheOpenDelay) {
10362 // No delay was set.
10363 return NS_ERROR_NOT_AVAILABLE;
10364 }
10365 if (!mCacheOpenFunc) {
10366 // There should be a runnable.
10367 return NS_ERROR_FAILURE;
10368 }
10369 if (mCacheOpenTimer) {
10370 rv = mCacheOpenTimer->Cancel();
10371 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10372 return rv;
10373 }
10374 mCacheOpenTimer = nullptr;
10375 }
10376 mCacheOpenDelay = 0;
10377 // Avoid re-entrancy issues by nulling our mCacheOpenFunc before calling it.
10378 std::function<void(nsHttpChannel*)> cacheOpenFunc = nullptr;
10379 std::swap(cacheOpenFunc, mCacheOpenFunc);
10380 cacheOpenFunc(this);
10381
10382 return NS_OK;
10383}
10384
10385nsresult nsHttpChannel::TriggerNetworkWithDelay(uint32_t aDelay) {
10386 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { *((volatile
int*)__null) = 10386; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10387
10388 LOG(("nsHttpChannel::TriggerNetworkWithDelay [this=%p, delay=%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::TriggerNetworkWithDelay [this=%p, delay=%u]\n"
, this, aDelay); } } while (0)
10389 aDelay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::TriggerNetworkWithDelay [this=%p, delay=%u]\n"
, this, aDelay); } } while (0)
;
10390
10391 if (mCanceled) {
10392 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)
;
10393 return mStatus;
10394 }
10395
10396 // If a network request has already gone out, there is no point in
10397 // doing this again.
10398 if (mNetworkTriggered) {
10399 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)
;
10400 return NS_OK;
10401 }
10402
10403 if (mNetworkTriggerDelay) {
10404 aDelay = mNetworkTriggerDelay;
10405 }
10406
10407 if (!aDelay) {
10408 // We cannot call TriggerNetwork() directly here, because it would
10409 // cause performance regression in tp6 tests, see bug 1398847.
10410 return NS_DispatchToMainThread(
10411 NewRunnableMethod("net::nsHttpChannel::TriggerNetworkWithDelay", this,
10412 &nsHttpChannel::TriggerNetwork),
10413 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
10414 }
10415
10416 MOZ_ASSERT(!mNetworkTriggerTimer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mNetworkTriggerTimer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mNetworkTriggerTimer))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!mNetworkTriggerTimer"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mNetworkTriggerTimer"
")"); do { *((volatile int*)__null) = 10416; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10417 mNetworkTriggerTimer = NS_NewTimer();
10418 auto callback = MakeRefPtr<TimerCallback>(this);
10419 LOG(("Creating new networkTriggertimer for 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
, "Creating new networkTriggertimer for delay"); } } while (0
)
;
10420 mNetworkTriggerTimer->InitWithCallback(callback, aDelay,
10421 nsITimer::TYPE_ONE_SHOT);
10422 return NS_OK;
10423}
10424
10425nsresult nsHttpChannel::TriggerNetwork() {
10426 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10426); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { *((volatile
int*)__null) = 10426; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10427
10428 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)
;
10429
10430 if (mCanceled) {
10431 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)
;
10432 return mStatus;
10433 }
10434
10435 // If a network request has already gone out, there is no point in
10436 // doing this again.
10437 if (mNetworkTriggered) {
10438 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)
;
10439 return NS_OK;
10440 }
10441
10442 mNetworkTriggered = true;
10443 if (mNetworkTriggerTimer) {
10444 mNetworkTriggerTimer->Cancel();
10445 mNetworkTriggerTimer = nullptr;
10446 }
10447
10448 // If we are waiting for a proxy request, that means we can't trigger
10449 // the next step just yet. We need for mConnectionInfo to be non-null
10450 // before we call ContinueConnect. OnProxyAvailable will trigger
10451 // BeginConnect, and Connect will call ContinueConnect even if it's
10452 // for the cache callbacks.
10453 if (mProxyRequest) {
10454 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)
;
10455 mWaitingForProxy = true;
10456 return NS_OK;
10457 }
10458
10459 // If |mCacheOpenFunc| is assigned, we're delaying opening the entry to
10460 // simulate racing. Although cache entry opening hasn't started yet, we're
10461 // actually racing, so we must set mRaceCacheWithNetwork to true now.
10462 mRaceCacheWithNetwork =
10463 AwaitingCacheCallbacks() &&
10464 (mCacheOpenFunc || StaticPrefs::network_http_rcwn_enabled());
10465
10466 LOG((" triggering network rcwn=%d\n", bool(mRaceCacheWithNetwork)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " triggering network rcwn=%d\n", bool(mRaceCacheWithNetwork
)); } } while (0)
;
10467 return ContinueConnect();
10468}
10469
10470void nsHttpChannel::MaybeRaceCacheWithNetwork() {
10471 nsresult rv;
10472
10473 nsCOMPtr<nsINetworkLinkService> netLinkSvc;
10474 netLinkSvc = do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID"@mozilla.org/network/network-link-service;1", &rv);
10475 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10476 return;
10477 }
10478
10479 uint32_t linkType;
10480 rv = netLinkSvc->GetLinkType(&linkType);
10481 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10482 return;
10483 }
10484
10485 if (!(linkType == nsINetworkLinkService::LINK_TYPE_ETHERNET ||
10486#ifndef MOZ_WIDGET_ANDROID
10487 // On Android we don't assume an unknown link type is unmetered
10488 linkType == nsINetworkLinkService::LINK_TYPE_UNKNOWN ||
10489#endif
10490 linkType == nsINetworkLinkService::LINK_TYPE_USB ||
10491 linkType == nsINetworkLinkService::LINK_TYPE_WIFI)) {
10492 return;
10493 }
10494
10495 // Don't trigger the network if the load flags say so.
10496 if (mLoadFlags & (LOAD_ONLY_FROM_CACHE | LOAD_NO_NETWORK_IO)) {
10497 return;
10498 }
10499
10500 // We must not race if the channel has a failure status code.
10501 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
10502 return;
10503 }
10504
10505 // If a CORS Preflight is required we must not race.
10506 if (LoadRequireCORSPreflight() && !LoadIsCorsPreflightDone()) {
10507 return;
10508 }
10509
10510 if (CacheFileUtils::CachePerfStats::IsCacheSlow()) {
10511 // If the cache is slow, trigger the network request immediately.
10512 mRaceDelay = 0;
10513 } else {
10514 // Give cache a headstart of 3 times the average cache entry open time.
10515 mRaceDelay = CacheFileUtils::CachePerfStats::GetAverage(
10516 CacheFileUtils::CachePerfStats::ENTRY_OPEN, true) *
10517 3;
10518 // We use microseconds in CachePerfStats but we need milliseconds
10519 // for TriggerNetwork.
10520 mRaceDelay /= 1000;
10521 }
10522
10523 mRaceDelay = clamped<uint32_t>(
10524 mRaceDelay, StaticPrefs::network_http_rcwn_min_wait_before_racing_ms(),
10525 StaticPrefs::network_http_rcwn_max_wait_before_racing_ms());
10526
10527 MOZ_ASSERT(StaticPrefs::network_http_rcwn_enabled() || mNetworkTriggerDelay,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::network_http_rcwn_enabled() || mNetworkTriggerDelay
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(StaticPrefs::network_http_rcwn_enabled() || mNetworkTriggerDelay
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"StaticPrefs::network_http_rcwn_enabled() || mNetworkTriggerDelay"
" (" "The pref must be turned on." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::network_http_rcwn_enabled() || mNetworkTriggerDelay"
") (" "The pref must be turned on." ")"); do { *((volatile int
*)__null) = 10528; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
10528 "The pref must be turned on.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::network_http_rcwn_enabled() || mNetworkTriggerDelay
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(StaticPrefs::network_http_rcwn_enabled() || mNetworkTriggerDelay
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"StaticPrefs::network_http_rcwn_enabled() || mNetworkTriggerDelay"
" (" "The pref must be turned on." ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::network_http_rcwn_enabled() || mNetworkTriggerDelay"
") (" "The pref must be turned on." ")"); do { *((volatile int
*)__null) = 10528; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10529 LOG(("nsHttpChannel::MaybeRaceCacheWithNetwork [this=%p, delay=%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::MaybeRaceCacheWithNetwork [this=%p, delay=%u]\n"
, this, mRaceDelay); } } while (0)
10530 mRaceDelay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeRaceCacheWithNetwork [this=%p, delay=%u]\n"
, this, mRaceDelay); } } while (0)
;
10531
10532 TriggerNetworkWithDelay(mRaceDelay);
10533}
10534
10535NS_IMETHODIMPnsresult
10536nsHttpChannel::Test_triggerNetwork(int32_t aTimeout) {
10537 LOG(("nsHttpChannel::Test_triggerNetwork this=%p timeout=%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::Test_triggerNetwork this=%p timeout=%d", this
, aTimeout); } } while (0)
10538 aTimeout))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Test_triggerNetwork this=%p timeout=%d", this
, aTimeout); } } while (0)
;
10539 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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { *((volatile
int*)__null) = 10539; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10540
10541 // We set the trigger delay to the specified timeout.
10542 mRaceCacheWithNetwork = true;
10543 mNetworkTriggerDelay = aTimeout;
10544
10545 // If we already have a timer, set the delay/
10546 if (mNetworkTriggerTimer) {
10547 // If the timeout is 0 and there is a timer, we can trigger
10548 // the network immediately.
10549 MOZ_ASSERT(LoadWasOpened(), "Must have been opened before")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
" (" "Must have been opened before" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10549); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()"
") (" "Must have been opened before" ")"); do { *((volatile int
*)__null) = 10549; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10550 if (!aTimeout) {
10551 return TriggerNetwork();
10552 }
10553 mNetworkTriggerTimer->SetDelay(aTimeout);
10554 }
10555 return NS_OK;
10556}
10557
10558nsHttpChannel::TimerCallback::TimerCallback(nsHttpChannel* aChannel)
10559 : mChannel(aChannel) {}
10560
10561NS_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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
10561; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10561; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 10561
; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10561; __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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10561); 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(
(sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
10562
10563NS_IMETHODIMPnsresult
10564nsHttpChannel::TimerCallback::GetName(nsACString& aName) {
10565 aName.AssignLiteral("nsHttpChannel");
10566 return NS_OK;
10567}
10568
10569NS_IMETHODIMPnsresult
10570nsHttpChannel::TimerCallback::Notify(nsITimer* aTimer) {
10571 if (aTimer == mChannel->mCacheOpenTimer) {
10572 return mChannel->Test_triggerDelayedOpenCacheEntry();
10573 }
10574 if (aTimer == mChannel->mNetworkTriggerTimer) {
10575 return mChannel->TriggerNetwork();
10576 }
10577 MOZ_CRASH("Unknown timer")do { do { } while (false); MOZ_ReportCrash("" "Unknown timer"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10577); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown timer"
")"); do { *((volatile int*)__null) = 10577; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
10578
10579 return NS_OK;
10580}
10581
10582bool nsHttpChannel::EligibleForTailing() {
10583 if (!(mClassOfService.Flags() & nsIClassOfService::Tail)) {
10584 return false;
10585 }
10586
10587 if (mClassOfService.Flags() &
10588 (nsIClassOfService::UrgentStart | nsIClassOfService::Leader |
10589 nsIClassOfService::TailForbidden)) {
10590 return false;
10591 }
10592
10593 if (mClassOfService.Flags() & nsIClassOfService::Unblocked &&
10594 !(mClassOfService.Flags() & nsIClassOfService::TailAllowed)) {
10595 return false;
10596 }
10597
10598 if (IsNavigation()) {
10599 return false;
10600 }
10601
10602 return true;
10603}
10604
10605bool nsHttpChannel::WaitingForTailUnblock() {
10606 nsresult rv;
10607
10608 if (!gHttpHandler->IsTailBlockingEnabled()) {
10609 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)
;
10610 return false;
10611 }
10612
10613 if (!EligibleForTailing()) {
10614 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)
;
10615 AddAsNonTailRequest();
10616 return false;
10617 }
10618
10619 if (!EnsureRequestContext()) {
10620 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)
;
10621 return false;
10622 }
10623
10624 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)
10625 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)
;
10626
10627 bool blocked;
10628 rv = mRequestContext->IsContextTailBlocked(this, &blocked);
10629 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10630 return false;
10631 }
10632
10633 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)
;
10634
10635 return blocked;
10636}
10637
10638//-----------------------------------------------------------------------------
10639// nsHttpChannel::nsIRequestTailUnblockCallback
10640//-----------------------------------------------------------------------------
10641
10642// Must be implemented in the leaf class because we don't have
10643// AsyncAbort in HttpBaseChannel.
10644NS_IMETHODIMPnsresult
10645nsHttpChannel::OnTailUnblock(nsresult rv) {
10646 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)
10647 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)
;
10648
10649 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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10649); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mOnTailUnblock"
")"); do { *((volatile int*)__null) = 10649; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10650
10651 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
10652 rv = mStatus;
10653 }
10654
10655 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10656 auto callback = mOnTailUnblock;
10657 mOnTailUnblock = nullptr;
10658 rv = (this->*callback)();
10659 }
10660
10661 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10662 CloseCacheEntry(false);
10663 return AsyncAbort(rv);
10664 }
10665
10666 return NS_OK;
10667}
10668
10669void nsHttpChannel::SetWarningReporter(
10670 HttpChannelSecurityWarningReporter* aReporter) {
10671 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)
;
10672 mWarningReporter = aReporter;
10673}
10674
10675HttpChannelSecurityWarningReporter* nsHttpChannel::GetWarningReporter() {
10676 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)
10677 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)
;
10678 return mWarningReporter.get();
10679}
10680
10681// The specification for ORB is currently being written:
10682// https://whatpr.org/fetch/1442.html#orb-algorithm
10683// The `opaque-response-safelist check` is implemented in:
10684// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff`
10685// * `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
10686// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff`
10687// * `OpaqueResponseBlocker::ValidateJavaScript`
10688//
10689// Should only be called by nsMediaSniffer::GetMIMETypeFromContent and
10690// imageLoader::GetMIMETypeFromContent when the content type can be
10691// recognized by these sniffers.
10692void nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck(
10693 SnifferType aType) {
10694 // https://whatpr.org/fetch/1442.html#orb-algorithm
10695 // This method covers steps, 8 and 10.
10696 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 10696; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10697
10698 if (NeedOpaqueResponseAllowedCheckAfterSniff()) {
10699 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedOpaqueResponseBlockingPref"
")"); do { *((volatile int*)__null) = 10699; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10700
10701 // If the sniffer type is media and the request comes from a media element,
10702 // we would like to check:
10703 // - Whether the information provided by the media element shows it's an
10704 // initial request.
10705 // - Whether the response's status is either 200 or 206.
10706 //
10707 // If any of the results is false, then we set
10708 // mBlockOpaqueResponseAfterSniff to true and block the response later.
10709 if (aType == SnifferType::Media) {
10710 // Step 8
10711 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo"
")"); do { *((volatile int*)__null) = 10711; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10712
10713 bool isMediaRequest;
10714 mLoadInfo->GetIsMediaRequest(&isMediaRequest);
10715 if (isMediaRequest) {
10716 bool isInitialRequest;
10717 mLoadInfo->GetIsMediaInitialRequest(&isInitialRequest);
10718 MOZ_ASSERT(isInitialRequest)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isInitialRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isInitialRequest))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("isInitialRequest"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isInitialRequest"
")"); do { *((volatile int*)__null) = 10718; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10719
10720 if (!isInitialRequest) {
10721 // Step 8.1
10722 BlockOpaqueResponseAfterSniff(
10723 u"media request after sniffing, but not initial request"_ns,
10724 OpaqueResponseBlockedTelemetryReason::MEDIA_NOT_INITIAL);
10725 return;
10726 }
10727
10728 if (mResponseHead->Status() != 200 && mResponseHead->Status() != 206) {
10729 // Step 8.2
10730 BlockOpaqueResponseAfterSniff(
10731 u"media request's response status is neither 200 nor 206"_ns,
10732 OpaqueResponseBlockedTelemetryReason::MEDIA_INCORRECT_RESP);
10733 return;
10734 }
10735 }
10736 }
10737
10738 // Step 8.3 if `aType == SnifferType::Media`
10739 // Step 9 can be skipped, only `HTMLMediaElement` ever sets isMediaRequest.
10740 // Step 10 if `aType == SnifferType::Image`
10741 AllowOpaqueResponseAfterSniff();
10742 }
10743}
10744
10745namespace {
10746
10747class CopyNonDefaultHeaderVisitor final : public nsIHttpHeaderVisitor {
10748 nsCOMPtr<nsIHttpChannel> mTarget;
10749
10750 ~CopyNonDefaultHeaderVisitor() = default;
10751
10752 NS_IMETHODvirtual nsresult
10753 VisitHeader(const nsACString& aHeader, const nsACString& aValue) override {
10754 if (aValue.IsEmpty()) {
10755 return mTarget->SetEmptyRequestHeader(aHeader);
10756 }
10757 return mTarget->SetRequestHeader(aHeader, aValue, false /* merge */);
10758 }
10759
10760 public:
10761 explicit CopyNonDefaultHeaderVisitor(nsIHttpChannel* aTarget)
10762 : mTarget(aTarget) {
10763 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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10763); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mTarget"
")"); do { *((volatile int*)__null) = 10763; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10764 }
10765
10766 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:
10767};
10768
10769NS_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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
10769; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10769; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 10769
; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10769; __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", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10769); 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((sizeof(table) / sizeof(table[0])) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
10770
10771} // anonymous namespace
10772
10773nsresult nsHttpChannel::RedirectToInterceptedChannel() {
10774 nsCOMPtr<nsINetworkInterceptController> controller;
10775 GetCallback(controller);
10776
10777 RefPtr<InterceptedHttpChannel> intercepted =
10778 InterceptedHttpChannel::CreateForInterception(
10779 mChannelCreationTime, mChannelCreationTimestamp, mAsyncOpenTime);
10780
10781 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
10782
10783 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
10784 CloneLoadInfoForRedirect(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
10785
10786 nsresult rv = intercepted->Init(
10787 mURI, mCaps, static_cast<nsProxyInfo*>(mProxyInfo.get()),
10788 mProxyResolveFlags, mProxyURI, mChannelId, type, redirectLoadInfo);
10789
10790 rv = SetupReplacementChannel(mURI, intercepted, true,
10791 nsIChannelEventSink::REDIRECT_INTERNAL);
10792 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10792); return rv; } } while (false)
;
10793
10794 // Some APIs, like fetch(), allow content to set non-standard headers.
10795 // Normally these APIs are responsible for copying these headers across
10796 // redirects. In the e10s parent-side intercept case, though, we currently
10797 // "hide" the internal redirect to the InterceptedHttpChannel. So the
10798 // fetch() API does not have the opportunity to move headers over.
10799 // Therefore, we do it automatically here.
10800 //
10801 // Once child-side interception is removed and the internal redirect no
10802 // longer needs to be "hidden", then this header copying code can be
10803 // removed.
10804 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
10805 new CopyNonDefaultHeaderVisitor(intercepted);
10806 rv = VisitNonDefaultRequestHeaders(visitor);
10807 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, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10807); return rv; } } while (false)
;
10808
10809 mRedirectChannel = intercepted;
10810
10811 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
10812
10813 rv = gHttpHandler->AsyncOnChannelRedirect(
10814 this, intercepted, nsIChannelEventSink::REDIRECT_INTERNAL);
10815
10816 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10817 rv = WaitForRedirectCallback();
10818 }
10819
10820 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10821 AutoRedirectVetoNotifier notifier(this, rv);
10822
10823 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
10824 }
10825
10826 return rv;
10827}
10828
10829void nsHttpChannel::ReEvaluateReferrerAfterTrackingStatusIsKnown() {
10830 nsCOMPtr<nsICookieJarSettings> cjs;
10831 if (mLoadInfo) {
10832 Unused << mLoadInfo->GetCookieJarSettings(getter_AddRefs(cjs));
10833 }
10834 if (!cjs) {
10835 cjs = net::CookieJarSettings::Create(mLoadInfo->GetLoadingPrincipal());
10836 }
10837 if (cjs->GetRejectThirdPartyContexts()) {
10838 bool isPrivate = mLoadInfo->GetOriginAttributes().IsPrivateBrowsing();
10839 // If our referrer has been set before, and our referrer policy is unset
10840 // (default policy) if we thought the channel wasn't a third-party
10841 // tracking channel, we may need to set our referrer with referrer policy
10842 // once again to ensure our defaults properly take effect now.
10843 if (mReferrerInfo) {
10844 ReferrerInfo* referrerInfo =
10845 static_cast<ReferrerInfo*>(mReferrerInfo.get());
10846
10847 if (referrerInfo->IsPolicyOverrided() &&
10848 referrerInfo->ReferrerPolicy() ==
10849 ReferrerInfo::GetDefaultReferrerPolicy(nullptr, nullptr,
10850 isPrivate)) {
10851 nsCOMPtr<nsIReferrerInfo> newReferrerInfo =
10852 referrerInfo->CloneWithNewPolicy(
10853 ReferrerInfo::GetDefaultReferrerPolicy(this, mURI, isPrivate));
10854 // The arguments passed to SetReferrerInfoInternal here should mirror
10855 // the arguments passed in
10856 // HttpChannelChild::RecvOverrideReferrerInfoDuringBeginConnect().
10857 SetReferrerInfoInternal(newReferrerInfo, false, true, true);
10858
10859 nsCOMPtr<nsIParentChannel> parentChannel;
10860 NS_QueryNotificationCallbacks(this, parentChannel);
10861 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
10862 if (httpParent) {
10863 httpParent->OverrideReferrerInfoDuringBeginConnect(newReferrerInfo);
10864 }
10865 }
10866 }
10867 }
10868}
10869
10870namespace {
10871
10872class BackgroundRevalidatingListener : public nsIStreamListener {
10873 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:
10874
10875 NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream
*aInputStream, uint64_t aOffset, uint32_t aCount) override;
10876 NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override
; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult
aStatusCode) override;
10877
10878 private:
10879 virtual ~BackgroundRevalidatingListener() = default;
10880};
10881
10882NS_IMETHODIMPnsresult
10883BackgroundRevalidatingListener::OnStartRequest(nsIRequest* request) {
10884 return NS_OK;
10885}
10886
10887NS_IMETHODIMPnsresult
10888BackgroundRevalidatingListener::OnDataAvailable(nsIRequest* request,
10889 nsIInputStream* input,
10890 uint64_t offset,
10891 uint32_t count) {
10892 uint32_t bytesRead = 0;
10893 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &bytesRead);
10894}
10895
10896NS_IMETHODIMPnsresult
10897BackgroundRevalidatingListener::OnStopRequest(nsIRequest* request,
10898 nsresult status) {
10899 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
10900 return status;
10901 }
10902
10903 nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(request));
10904 if (gHttpHandler) {
10905 gHttpHandler->OnBackgroundRevalidation(channel);
10906 }
10907 return NS_OK;
10908}
10909
10910NS_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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
10911; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10911; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 10911
; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10911; __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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); MOZ_PretendNoReturn(); } } while (0); nsresult rv =
NS_ERROR_FAILURE; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<BackgroundRevalidatingListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((BackgroundRevalidatingListener*)0x1000)) - reinterpret_cast
<char*>((BackgroundRevalidatingListener*)0x1000))}, {&
mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIStreamListener*>((
BackgroundRevalidatingListener*)0x1000))) - reinterpret_cast<
char*>((BackgroundRevalidatingListener*)0x1000))}, { nullptr
, 0 } } ; static_assert((sizeof(table) / sizeof(table[0])) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
10911 nsIRequestObserver)MozExternalRefCountType BackgroundRevalidatingListener::AddRef
(void) { static_assert(!std::is_destructible_v<BackgroundRevalidatingListener
>, "Reference-counted class " "BackgroundRevalidatingListener"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
10911; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10911; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 10911
; __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" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 10911; __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"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10911); MOZ_PretendNoReturn(); } } while (0); nsresult rv =
NS_ERROR_FAILURE; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<BackgroundRevalidatingListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((BackgroundRevalidatingListener*)0x1000)) - reinterpret_cast
<char*>((BackgroundRevalidatingListener*)0x1000))}, {&
mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIStreamListener*>((
BackgroundRevalidatingListener*)0x1000))) - reinterpret_cast<
char*>((BackgroundRevalidatingListener*)0x1000))}, { nullptr
, 0 } } ; static_assert((sizeof(table) / sizeof(table[0])) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
10912
10913} // namespace
10914
10915void nsHttpChannel::PerformBackgroundCacheRevalidation() {
10916 if (!StaticPrefs::network_http_stale_while_revalidate_enabled()) {
10917 return;
10918 }
10919
10920 // This is a channel doing a revalidation. It shouldn't do it again.
10921 if (mStaleRevalidation) {
10922 return;
10923 }
10924
10925 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)
;
10926
10927 Unused << NS_DispatchToMainThreadQueue(
10928 NewIdleRunnableMethod(
10929 "nsHttpChannel::PerformBackgroundCacheRevalidation", this,
10930 &nsHttpChannel::PerformBackgroundCacheRevalidationNow),
10931 EventQueuePriority::Idle);
10932}
10933
10934void nsHttpChannel::PerformBackgroundCacheRevalidationNow() {
10935 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)
;
10936
10937 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()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsHttpChannel.cpp"
, 10937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 10937; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10938
10939 nsresult rv;
10940
10941 nsLoadFlags loadFlags = mLoadFlags | LOAD_ONLY_IF_MODIFIED | VALIDATE_ALWAYS |
10942 LOAD_BACKGROUND | LOAD_BYPASS_SERVICE_WORKER;
10943
10944 nsCOMPtr<nsIChannel> validatingChannel;
10945 rv = NS_NewChannelInternal(getter_AddRefs(validatingChannel), mURI, mLoadInfo,
10946 nullptr /* performance storage */, mLoadGroup,
10947 mCallbacks, loadFlags);
10948 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10949 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)
10950 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)
;
10951 return;
10952 }
10953
10954 nsCOMPtr<nsISupportsPriority> priority(do_QueryInterface(validatingChannel));
10955 if (priority) {
10956 priority->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
10957 }
10958
10959 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(validatingChannel));
10960 if (cos) {
10961 cos->AddClassFlags(nsIClassOfService::Tail);
10962 }
10963
10964 RefPtr<nsHttpChannel> httpChan = do_QueryObject(validatingChannel);
10965 if (httpChan) {
10966 httpChan->mStaleRevalidation = true;
10967 }
10968
10969 RefPtr<BackgroundRevalidatingListener> listener =
10970 new BackgroundRevalidatingListener();
10971 rv = validatingChannel->AsyncOpen(listener);
10972 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10973 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)
;
10974 return;
10975 }
10976
10977 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)
10978 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)
;
10979}
10980
10981NS_IMETHODIMPnsresult
10982nsHttpChannel::SetEarlyHintObserver(nsIEarlyHintObserver* aObserver) {
10983 mEarlyHintObserver = aObserver;
10984 return NS_OK;
10985}
10986
10987NS_IMETHODIMPnsresult
10988nsHttpChannel::EarlyHint(const nsACString& aLinkHeader,
10989 const nsACString& aReferrerPolicy,
10990 const nsACString& aCspHeader) {
10991 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)
;
10992
10993 if (mEarlyHintObserver && nsContentUtils::ComputeIsSecureContext(this)) {
10994 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)
;
10995 mEarlyHintObserver->EarlyHint(aLinkHeader, aReferrerPolicy, aCspHeader);
10996 }
10997 return NS_OK;
10998}
10999
11000NS_IMETHODIMPnsresult nsHttpChannel::SetResponseOverride(
11001 nsIReplacedHttpResponse* aReplacedHttpResponse) {
11002 mOverrideResponse = new nsMainThreadPtrHolder<nsIReplacedHttpResponse>(
11003 "nsIReplacedHttpResponse", aReplacedHttpResponse);
11004 return NS_OK;
11005}
11006
11007NS_IMETHODIMPnsresult nsHttpChannel::SetResponseStatus(uint32_t aStatus,
11008 const nsACString& aStatusText) {
11009 if (!mResponseHead) {
11010 return NS_ERROR_NOT_AVAILABLE;
11011 }
11012
11013 nsAutoCString statusText(aStatusText);
11014 nsAutoCString protocolVersion(
11015 nsHttp::GetProtocolVersion(mResponseHead->Version()));
11016 ToUpperCase(protocolVersion);
11017
11018 nsPrintfCString line("%s %u %s", protocolVersion.get(), aStatus,
11019 statusText.get());
11020
11021 return mResponseHead->ParseStatusLine(line);
11022}
11023
11024NS_IMETHODIMPnsresult nsHttpChannel::SetWebTransportSessionEventListener(
11025 WebTransportSessionEventListener* aListener) {
11026 mWebTransportSessionEventListener = aListener;
11027 return NS_OK;
11028}
11029
11030already_AddRefed<WebTransportSessionEventListener>
11031nsHttpChannel::GetWebTransportSessionEventListener() {
11032 RefPtr<WebTransportSessionEventListener> wt =
11033 mWebTransportSessionEventListener;
11034 return wt.forget();
11035}
11036
11037NS_IMETHODIMPnsresult nsHttpChannel::GetLastTransportStatus(
11038 nsresult* aLastTransportStatus) {
11039 *aLastTransportStatus = mLastTransportStatus;
11040 return NS_OK;
11041}
11042
11043} // namespace net
11044} // namespace mozilla