Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_protocol_http2.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_APP_UA_NAME="" -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/netwerk/protocol/http -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -I /root/firefox-clang/dom/base -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/cookie -I /root/firefox-clang/netwerk/dns -I /root/firefox-clang/netwerk/ipc -I /root/firefox-clang/netwerk/socket/neqo_glue -I /root/firefox-clang/netwerk/url-classifier -I /root/firefox-clang/extensions/auth -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-05-001426-257175-1 -x c++ Unified_cpp_protocol_http2.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5// HttpLog.h should generally be included first
6#include "mozilla/net/HttpBaseChannel.h"
7
8#include <algorithm>
9#include <utility>
10
11#include "HttpBaseChannel.h"
12#include "HttpLog.h"
13#include "LoadInfo.h"
14#include "ReferrerInfo.h"
15#include "mozIRemoteLazyInputStream.h"
16#include "mozIThirdPartyUtil.h"
17#include "mozilla/AntiTrackingUtils.h"
18#include "mozilla/BasePrincipal.h"
19#include "mozilla/BinarySearch.h"
20#include "mozilla/CompactPair.h"
21#include "mozilla/Components.h"
22#include "mozilla/ConsoleReportCollector.h"
23#include "mozilla/DebugOnly.h"
24#include "mozilla/InputStreamLengthHelper.h"
25#include "mozilla/LoadInfo.h"
26#include "mozilla/MathAlgorithms.h"
27#include "mozilla/Mutex.h"
28#include "mozilla/NullPrincipal.h"
29#include "mozilla/PermissionManager.h"
30#include "mozilla/RemoteLazyInputStreamChild.h"
31#include "mozilla/StaticPrefs_browser.h"
32#include "mozilla/StaticPrefs_fission.h"
33#include "mozilla/StaticPrefs_javascript.h"
34#include "mozilla/StaticPrefs_network.h"
35#include "mozilla/StaticPrefs_security.h"
36#include "mozilla/Telemetry.h"
37#include "mozilla/Tokenizer.h"
38#include "mozilla/browser/NimbusFeatures.h"
39#include "mozilla/dom/BrowsingContext.h"
40#include "mozilla/dom/CanonicalBrowsingContext.h"
41#include "mozilla/dom/ContentChild.h"
42#include "mozilla/dom/Document.h"
43#include "mozilla/dom/FetchPriority.h"
44#include "mozilla/dom/LoadURIOptionsBinding.h"
45#include "mozilla/dom/ParentProcessChannelHandle.h"
46#include "mozilla/dom/Performance.h"
47#include "mozilla/dom/PerformanceStorage.h"
48#include "mozilla/dom/PolicyContainer.h"
49#include "mozilla/dom/ProcessIsolation.h"
50#include "mozilla/dom/RequestBinding.h"
51#include "mozilla/dom/WindowGlobalParent.h"
52#include "mozilla/dom/nsHTTPSOnlyUtils.h"
53#include "mozilla/dom/nsMixedContentBlocker.h"
54#include "mozilla/glean/NetwerkProtocolHttpMetrics.h"
55#include "mozilla/net/ChannelClassifierUtils.h"
56#include "mozilla/net/OpaqueResponseUtils.h"
57#include "mozilla/net/SFV.h"
58#include "nsBufferedStreams.h"
59#include "nsCOMPtr.h"
60#include "nsCRT.h"
61#include "nsContentSecurityManager.h"
62#include "nsContentSecurityUtils.h"
63#include "nsContentUtils.h"
64#include "nsDebug.h"
65#include "nsEscape.h"
66#include "nsGlobalWindowInner.h"
67#include "nsGlobalWindowOuter.h"
68#include "nsHTTPCompressConv.h"
69#include "nsHttpChannel.h"
70#include "nsHttpHandler.h"
71#include "nsICacheInfoChannel.h"
72#include "nsICachingChannel.h"
73#include "nsIChannelEventSink.h"
74#include "nsIConsoleService.h"
75#include "nsIContentPolicy.h"
76#include "nsICookieService.h"
77#include "nsIDNSService.h"
78#include "nsIDOMWindowUtils.h"
79#include "nsIDocShell.h"
80#include "nsIEncodedChannel.h"
81#include "nsIHttpHeaderVisitor.h"
82#include "nsIMIMEInputStream.h"
83#include "nsIMultiplexInputStream.h"
84#include "nsIMutableArray.h"
85#include "nsINetworkInterceptController.h"
86#include "nsIOService.h"
87#include "nsIObserverService.h"
88#include "nsIPrincipal.h"
89#include "nsIProtocolProxyService.h"
90#include "nsIScriptError.h"
91#include "nsIScriptSecurityManager.h"
92#include "nsISecurityConsoleMessage.h"
93#include "nsISeekableStream.h"
94#include "nsIStorageStream.h"
95#include "nsIStreamConverterService.h"
96#include "nsITimedChannel.h"
97#include "nsITransportSecurityInfo.h"
98#include "nsIURIMutator.h"
99#include "nsMimeTypes.h"
100#include "nsNetCID.h"
101#include "nsNetUtil.h"
102#include "nsPIDOMWindow.h"
103#include "nsProxyRelease.h"
104#include "nsQueryObject.h"
105#include "nsReadableUtils.h"
106#include "nsRedirectHistoryEntry.h"
107#include "nsServerTiming.h"
108#include "nsStreamListenerWrapper.h"
109#include "nsStreamUtils.h"
110#include "nsString.h"
111#include "nsThreadUtils.h"
112#include "nsURLHelper.h"
113
114using mozilla::dom::ForceMediaDocument;
115using mozilla::dom::RequestMode;
116
117#define LOGORB(msg, ...) \
118 MOZ_LOG(GetORBLog(), LogLevel::Debug, \do { const ::mozilla::LogModule* moz_real_module = GetORBLog(
); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "%s: %p " msg, __func__, this, ##__VA_ARGS__
); } } while (0)
119 ("%s: %p " msg, __func__, this, ##__VA_ARGS__))do { const ::mozilla::LogModule* moz_real_module = GetORBLog(
); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "%s: %p " msg, __func__, this, ##__VA_ARGS__
); } } while (0)
120
121namespace mozilla {
122namespace net {
123
124static bool IsHeaderBlacklistedForRedirectCopy(nsHttpAtom const& aHeader) {
125 // IMPORTANT: keep this list ASCII-code sorted
126 static nsHttpAtomLiteral const* blackList[] = {
127 &nsHttp::Accept,
128 &nsHttp::Accept_Encoding,
129 &nsHttp::Accept_Language,
130 &nsHttp::Alternate_Service_Used,
131 &nsHttp::Authentication,
132 &nsHttp::Authorization,
133 &nsHttp::Connection,
134 &nsHttp::Content_Length,
135 &nsHttp::Cookie,
136 &nsHttp::Host,
137 &nsHttp::If,
138 &nsHttp::If_Match,
139 &nsHttp::If_Modified_Since,
140 &nsHttp::If_None_Match,
141 &nsHttp::If_None_Match_Any,
142 &nsHttp::If_Range,
143 &nsHttp::If_Unmodified_Since,
144 &nsHttp::Proxy_Authenticate,
145 &nsHttp::Proxy_Authorization,
146 &nsHttp::Range,
147 &nsHttp::TE,
148 &nsHttp::Transfer_Encoding,
149 &nsHttp::Upgrade,
150 &nsHttp::User_Agent,
151 &nsHttp::WWW_Authenticate};
152
153 class HttpAtomComparator {
154 nsHttpAtom const& mTarget;
155
156 public:
157 explicit HttpAtomComparator(nsHttpAtom const& aTarget) : mTarget(aTarget) {}
158 int operator()(nsHttpAtom const* aVal) const {
159 if (mTarget == *aVal) {
160 return 0;
161 }
162 return strcmp(mTarget.get(), aVal->get());
163 }
164 int operator()(nsHttpAtomLiteral const* aVal) const {
165 if (mTarget == *aVal) {
166 return 0;
167 }
168 return strcmp(mTarget.get(), aVal->get());
169 }
170 };
171
172 size_t unused;
173 return BinarySearchIf(blackList, 0, std::size(blackList),
174 HttpAtomComparator(aHeader), &unused);
175}
176
177class AddHeadersToChannelVisitor final : public nsIHttpHeaderVisitor {
178 public:
179 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:
180
181 explicit AddHeadersToChannelVisitor(nsIHttpChannel* aChannel)
182 : mChannel(aChannel) {}
183
184 NS_IMETHODvirtual nsresult VisitHeader(const nsACString& aHeader,
185 const nsACString& aValue) override {
186 nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
187 if (!IsHeaderBlacklistedForRedirectCopy(atom)) {
188 DebugOnly<nsresult> rv =
189 mChannel->SetRequestHeader(aHeader, aValue, false);
190 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 190); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 190); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
191 }
192 return NS_OK;
193 }
194
195 private:
196 ~AddHeadersToChannelVisitor() = default;
197
198 nsCOMPtr<nsIHttpChannel> mChannel;
199};
200
201NS_IMPL_ISUPPORTS(AddHeadersToChannelVisitor, nsIHttpHeaderVisitor)MozExternalRefCountType AddHeadersToChannelVisitor::AddRef(void
) { static_assert(!std::is_destructible_v<AddHeadersToChannelVisitor
>, "Reference-counted class " "AddHeadersToChannelVisitor"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 201
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("AddHeadersToChannelVisitor" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("AddHeadersToChannelVisitor" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"AddHeadersToChannelVisitor\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"AddHeadersToChannelVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 201); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("AddHeadersToChannelVisitor" " not thread-safe"); nsrefcnt count
= ++mRefCnt; NS_LogAddRef((this), (count), ("AddHeadersToChannelVisitor"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
AddHeadersToChannelVisitor::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 201
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("AddHeadersToChannelVisitor" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("AddHeadersToChannelVisitor" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"AddHeadersToChannelVisitor\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"AddHeadersToChannelVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 201); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("AddHeadersToChannelVisitor" " not thread-safe"); const char
* const nametmp = "AddHeadersToChannelVisitor"; nsrefcnt count
= --mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (
count == 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult AddHeadersToChannelVisitor::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 201); 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<AddHeadersToChannelVisitor, nsIHttpHeaderVisitor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIHttpHeaderVisitor
*>((AddHeadersToChannelVisitor*)0x1000)) - reinterpret_cast
<char*>((AddHeadersToChannelVisitor*)0x1000))}, {&mozilla
::detail::kImplementedIID<AddHeadersToChannelVisitor, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIHttpHeaderVisitor*>((AddHeadersToChannelVisitor
*)0x1000))) - reinterpret_cast<char*>((AddHeadersToChannelVisitor
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
202
203static OpaqueResponseFilterFetch ConfiguredFilterFetchResponseBehaviour() {
204 uint32_t pref = StaticPrefs::
205 browser_opaqueResponseBlocking_filterFetchResponse_DoNotUseDirectly();
206 if (NS_WARN_IF(pref >NS_warn_if_impl(pref > static_cast<uint32_t>(OpaqueResponseFilterFetch
::All), "pref > static_cast<uint32_t>(OpaqueResponseFilterFetch::All)"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 207
)
207 static_cast<uint32_t>(OpaqueResponseFilterFetch::All))NS_warn_if_impl(pref > static_cast<uint32_t>(OpaqueResponseFilterFetch
::All), "pref > static_cast<uint32_t>(OpaqueResponseFilterFetch::All)"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 207
)
) {
208 return OpaqueResponseFilterFetch::All;
209 }
210
211 return static_cast<OpaqueResponseFilterFetch>(pref);
212}
213
214HttpBaseChannel::HttpBaseChannel()
215 : mReportCollector(new ConsoleReportCollector()),
216 mHttpHandler(gHttpHandler),
217 mClassOfService(0, false),
218 mRequestMode(RequestMode::No_cors),
219 mRedirectionLimit(gHttpHandler->RedirectionLimit()),
220 mCachedOpaqueResponseBlockingPref(
221 StaticPrefs::browser_opaqueResponseBlocking()) {
222 StoreApplyConversion(true);
223 StoreAllowSTS(true);
224 StoreTracingEnabled(true);
225 StoreReportTiming(true);
226 StoreAllowSpdy(true);
227 StoreAllowHttp3(true);
228 StoreAllowAltSvc(true);
229 StoreResponseTimeoutEnabled(true);
230 StoreAllRedirectsSameOrigin(true);
231 StoreAllRedirectsSameOriginIgnoringInternal(true);
232 StoreAllRedirectsPassTimingAllowCheck(true);
233 StoreUpgradableToSecure(true);
234 StoreIsUserAgentHeaderModified(false);
235
236 this->mSelfAddr.inet = {};
237 this->mPeerAddr.inet = {};
238 LOG(("Creating HttpBaseChannel @%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 HttpBaseChannel @%p\n", this); } } while (0)
;
239
240 // Subfields of unions cannot be targeted in an initializer list.
241#ifdef MOZ_VALGRIND
242 // Zero the entire unions so that Valgrind doesn't complain when we send them
243 // to another process.
244 memset(&mSelfAddr, 0, sizeof(NetAddr));
245 memset(&mPeerAddr, 0, sizeof(NetAddr));
246#endif
247 mSelfAddr.raw.family = PR_AF_UNSPEC0;
248 mPeerAddr.raw.family = PR_AF_UNSPEC0;
249}
250
251HttpBaseChannel::~HttpBaseChannel() {
252 LOG(("Destroying HttpBaseChannel @%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 HttpBaseChannel @%p\n", this); } } while (0)
;
253
254 // Make sure we don't leak
255 CleanRedirectCacheChainIfNecessary();
256
257 ReleaseMainThreadOnlyReferences();
258}
259
260namespace { // anon
261
262class NonTailRemover : public nsISupports {
263 NS_DECL_THREADSAFE_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::true_type; protected
: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; nsAutoOwningThread
_mOwningThread; public:
264
265 explicit NonTailRemover(nsIRequestContext* rc) : mRequestContext(rc) {}
266
267 private:
268 virtual ~NonTailRemover() {
269 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 269
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 269); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
270 mRequestContext->RemoveNonTailRequest();
271 }
272
273 nsCOMPtr<nsIRequestContext> mRequestContext;
274};
275
276NS_IMPL_ISUPPORTS0(NonTailRemover)MozExternalRefCountType NonTailRemover::AddRef(void) { static_assert
(!std::is_destructible_v<NonTailRemover>, "Reference-counted class "
"NonTailRemover" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 276
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("NonTailRemover" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("NonTailRemover" != nullptr)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"NonTailRemover\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"NonTailRemover\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 276); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("NonTailRemover" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("NonTailRemover"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType NonTailRemover
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 276
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("NonTailRemover" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("NonTailRemover" != nullptr)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"NonTailRemover\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"NonTailRemover\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 276); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("NonTailRemover" " not thread-safe"); const char* const nametmp
= "NonTailRemover"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult NonTailRemover::
QueryInterface(const nsIID& aIID, void** aInstancePtr) { do
{ if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 276); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<NonTailRemover, nsISupports>, int32_t
( reinterpret_cast<char*>(static_cast<nsISupports*>
((NonTailRemover*)0x1000)) - reinterpret_cast<char*>((NonTailRemover
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
277
278} // namespace
279
280void HttpBaseChannel::ReleaseMainThreadOnlyReferences() {
281 if (NS_IsMainThread()) {
282 // Already on main thread, let dtor to
283 // take care of releasing references
284 RemoveAsNonTailRequest();
285 return;
286 }
287
288 nsTArray<nsCOMPtr<nsISupports>> arrayToRelease;
289 arrayToRelease.AppendElement(mLoadGroup.forget());
290 arrayToRelease.AppendElement(mLoadInfo.forget());
291 arrayToRelease.AppendElement(mCallbacks.forget());
292 arrayToRelease.AppendElement(mProgressSink.forget());
293 arrayToRelease.AppendElement(mPrincipal.forget());
294 arrayToRelease.AppendElement(mListener.forget());
295 arrayToRelease.AppendElement(mCompressListener.forget());
296 arrayToRelease.AppendElement(mORB.forget());
297
298 if (LoadAddedAsNonTailRequest()) {
299 // RemoveNonTailRequest() on our request context must be called on the main
300 // thread
301 MOZ_RELEASE_ASSERT(mRequestContext,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRequestContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRequestContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mRequestContext"
" (" "Someone released rc or set flags w/o having it?" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 302); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mRequestContext"
") (" "Someone released rc or set flags w/o having it?" ")")
; do { MOZ_CrashSequence(__null, 302); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
302 "Someone released rc or set flags w/o having it?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRequestContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRequestContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mRequestContext"
" (" "Someone released rc or set flags w/o having it?" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 302); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mRequestContext"
") (" "Someone released rc or set flags w/o having it?" ")")
; do { MOZ_CrashSequence(__null, 302); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
303
304 nsCOMPtr<nsISupports> nonTailRemover(new NonTailRemover(mRequestContext));
305 arrayToRelease.AppendElement(nonTailRemover.forget());
306 }
307
308 NS_DispatchToMainThread(new ProxyReleaseRunnable(std::move(arrayToRelease)));
309}
310
311void HttpBaseChannel::AddClassificationFlags(uint32_t aClassificationFlags,
312 bool aIsThirdParty) {
313 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::AddClassificationFlags classificationFlags=%d "
"thirdparty=%d %p", aClassificationFlags, static_cast<int
>(aIsThirdParty), this); } } while (0)
314 ("HttpBaseChannel::AddClassificationFlags classificationFlags=%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
, "HttpBaseChannel::AddClassificationFlags classificationFlags=%d "
"thirdparty=%d %p", aClassificationFlags, static_cast<int
>(aIsThirdParty), this); } } while (0)
315 "thirdparty=%d %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
, "HttpBaseChannel::AddClassificationFlags classificationFlags=%d "
"thirdparty=%d %p", aClassificationFlags, static_cast<int
>(aIsThirdParty), this); } } while (0)
316 aClassificationFlags, static_cast<int>(aIsThirdParty), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::AddClassificationFlags classificationFlags=%d "
"thirdparty=%d %p", aClassificationFlags, static_cast<int
>(aIsThirdParty), this); } } while (0)
;
317
318 if (aIsThirdParty) {
319 mThirdPartyClassificationFlags |= aClassificationFlags;
320 } else {
321 mFirstPartyClassificationFlags |= aClassificationFlags;
322 }
323}
324
325static bool isSecureOrTrustworthyURL(nsIURI* aURI) {
326 return aURI->SchemeIs("https") ||
327 (StaticPrefs::network_http_encoding_trustworthy_is_https() &&
328 nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI));
329}
330
331nsresult HttpBaseChannel::Init(nsIURI* aURI, uint32_t aCaps,
332 nsProxyInfo* aProxyInfo,
333 uint32_t aProxyResolveFlags, nsIURI* aProxyURI,
334 uint64_t aChannelId, nsILoadInfo* aLoadInfo) {
335 LOG1(("HttpBaseChannel::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, "HttpBaseChannel::Init [this=%p]\n"
, this); } } while (0)
;
336
337 MOZ_ASSERT(aURI, "null uri")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "null uri" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "null uri"
")"); do { MOZ_CrashSequence(__null, 337); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
338
339 mURI = aURI;
340 mOriginalURI = aURI;
341 mDocumentURI = nullptr;
342 mCaps = aCaps;
343 mProxyResolveFlags = aProxyResolveFlags;
344 mProxyURI = aProxyURI;
345 mChannelId = aChannelId;
346 mLoadInfo = aLoadInfo;
347
348 // Construct connection info object
349 nsAutoCString host;
350 int32_t port = -1;
351 bool isHTTPS = isSecureOrTrustworthyURL(mURI);
352
353 nsresult rv = mURI->GetAsciiHost(host);
354 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
355
356 // Reject the URL if it doesn't specify a host
357 if (host.IsEmpty()) return NS_ERROR_MALFORMED_URI;
358
359 rv = mURI->GetPort(&port);
360 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
361
362 LOG1(("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::Error)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Error, "host=%s port=%d\n"
, host.get(), port); } } while (0)
;
363
364 rv = mURI->GetAsciiSpec(mSpec);
365 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
366 LOG1(("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::Error)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Error, "uri=%s\n"
, mSpec.get()); } } while (0)
;
367
368 // Assert default request method
369 MOZ_ASSERT(mRequestHead.EqualsMethod(nsHttpRequestHead::kMethod_Get))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRequestHead.EqualsMethod(nsHttpRequestHead::kMethod_Get
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRequestHead.EqualsMethod(nsHttpRequestHead::kMethod_Get
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mRequestHead.EqualsMethod(nsHttpRequestHead::kMethod_Get)",
"./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 369
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestHead.EqualsMethod(nsHttpRequestHead::kMethod_Get)"
")"); do { MOZ_CrashSequence(__null, 369); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
370
371 // Set request headers
372 nsAutoCString hostLine;
373 rv = nsHttpHandler::GenerateHostPort(host, port, hostLine);
374 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
375
376 rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
377 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
378
379 // Override the Accept header if a specific MediaDocument kind is forced.
380 ExtContentPolicy contentPolicyType =
381 mLoadInfo->GetExternalContentPolicyType();
382 // TRRLoadInfo doesn't implement GetForceMediaDocument.
383 ForceMediaDocument forceMediaDocument;
384 if (NS_SUCCEEDED(mLoadInfo->GetForceMediaDocument(&forceMediaDocument))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetForceMediaDocument
(&forceMediaDocument))), 1)))
) {
385 switch (forceMediaDocument) {
386 case ForceMediaDocument::Image:
387 contentPolicyType = ExtContentPolicy::TYPE_IMAGE;
388 break;
389 case ForceMediaDocument::Video:
390 contentPolicyType = ExtContentPolicy::TYPE_MEDIA;
391 break;
392 case ForceMediaDocument::None:
393 break;
394 }
395 }
396
397 RefPtr<mozilla::dom::BrowsingContext> browsingContext;
398 mLoadInfo->GetBrowsingContext(getter_AddRefs(browsingContext));
399 if (!browsingContext) {
400 mLoadInfo->GetAssociatedBrowsingContext(getter_AddRefs(browsingContext));
401 }
402
403 const nsCString& languageOverride =
404 browsingContext ? browsingContext->Top()->GetLanguageOverride()
405 : EmptyCString();
406
407 rv = gHttpHandler->AddStandardRequestHeaders(
408 &mRequestHead, aURI, isHTTPS, contentPolicyType,
409 nsContentUtils::ShouldResistFingerprinting(this,
410 RFPTarget::HttpUserAgent),
411 languageOverride);
412 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
413
414 nsAutoCString type;
415 if (aProxyInfo && NS_SUCCEEDED(aProxyInfo->GetType(type))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProxyInfo->GetType
(type))), 1)))
&&
416 !type.EqualsLiteral("unknown")) {
417 mProxyInfo = aProxyInfo;
418 }
419
420 mCurrentThread = GetCurrentSerialEventTarget();
421 return rv;
422}
423
424//-----------------------------------------------------------------------------
425// HttpBaseChannel::nsISupports
426//-----------------------------------------------------------------------------
427
428NS_IMPL_ADDREF(HttpBaseChannel)MozExternalRefCountType HttpBaseChannel::AddRef(void) { static_assert
(!std::is_destructible_v<HttpBaseChannel>, "Reference-counted class "
"HttpBaseChannel" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 428
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("HttpBaseChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("HttpBaseChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"HttpBaseChannel\" != nullptr" " (" "Must specify a name" ")"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 428
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 428); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("HttpBaseChannel" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("HttpBaseChannel"), (uint32_t
)(sizeof(*this))); return count; }
429NS_IMPL_RELEASE(HttpBaseChannel)MozExternalRefCountType HttpBaseChannel::Release(void) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 429); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 429
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("HttpBaseChannel" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("HttpBaseChannel" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"HttpBaseChannel\" != nullptr" " (" "Must specify a name" ")"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 429
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 429); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("HttpBaseChannel" " not thread-safe"); const char* const nametmp
= "HttpBaseChannel"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; }
430
431NS_INTERFACE_MAP_BEGIN(HttpBaseChannel)nsresult HttpBaseChannel::QueryInterface(const nsIID& aIID
, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 431); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
432 NS_INTERFACE_MAP_ENTRY(nsIRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequest>)) foundInterface = static_cast
<nsIRequest*>(this); else
433 NS_INTERFACE_MAP_ENTRY(nsIChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIChannel>)) foundInterface = static_cast
<nsIChannel*>(this); else
434 NS_INTERFACE_MAP_ENTRY(nsIIdentChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIIdentChannel>)) foundInterface
= static_cast<nsIIdentChannel*>(this); else
435 NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIEncodedChannel>)) foundInterface
= static_cast<nsIEncodedChannel*>(this); else
436 NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannel>)) foundInterface =
static_cast<nsIHttpChannel*>(this); else
437 NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannelInternal>)) foundInterface
= static_cast<nsIHttpChannelInternal*>(this); else
438 NS_INTERFACE_MAP_ENTRY(nsIForcePendingChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIForcePendingChannel>)) foundInterface
= static_cast<nsIForcePendingChannel*>(this); else
439 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel>)) foundInterface
= static_cast<nsIUploadChannel*>(this); else
440 NS_INTERFACE_MAP_ENTRY(nsIFormPOSTActionChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIFormPOSTActionChannel>)) foundInterface
= static_cast<nsIFormPOSTActionChannel*>(this); else
441 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel2>)) foundInterface
= static_cast<nsIUploadChannel2*>(this); else
442 NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsPriority>)) foundInterface
= static_cast<nsISupportsPriority*>(this); else
443 NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsITraceableChannel>)) foundInterface
= static_cast<nsITraceableChannel*>(this); else
444 NS_INTERFACE_MAP_ENTRY(nsIPrivateBrowsingChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIPrivateBrowsingChannel>)) foundInterface
= static_cast<nsIPrivateBrowsingChannel*>(this); else
445 NS_INTERFACE_MAP_ENTRY(nsITimedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsITimedChannel>)) foundInterface
= static_cast<nsITimedChannel*>(this); else
446 NS_INTERFACE_MAP_ENTRY(nsIConsoleReportCollector)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIConsoleReportCollector>)) foundInterface
= static_cast<nsIConsoleReportCollector*>(this); else
447 NS_INTERFACE_MAP_ENTRY(nsIThrottledInputChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThrottledInputChannel>)) foundInterface
= static_cast<nsIThrottledInputChannel*>(this); else
448 NS_INTERFACE_MAP_ENTRY(nsIClassifiedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIClassifiedChannel>)) foundInterface
= static_cast<nsIClassifiedChannel*>(this); else
449 NS_INTERFACE_MAP_ENTRY_CONCRETE(HttpBaseChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, HttpBaseChannel>)) { *aInstancePtr
= do_AddRef(static_cast<HttpBaseChannel*>(this)).take(
); return NS_OK; } else
450NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)foundInterface = 0; nsresult status; if (!foundInterface) status
= nsHashPropertyBag::QueryInterface(aIID, (void**)&foundInterface
); else { (foundInterface)->AddRef(); status = NS_OK; } *aInstancePtr
= foundInterface; return status; }
451
452//-----------------------------------------------------------------------------
453// HttpBaseChannel::nsIRequest
454//-----------------------------------------------------------------------------
455
456NS_IMETHODIMPnsresult
457HttpBaseChannel::GetName(nsACString& aName) {
458 aName = mSpec;
459 return NS_OK;
460}
461
462NS_IMETHODIMPnsresult
463HttpBaseChannel::IsPending(bool* aIsPending) {
464 NS_ENSURE_ARG_POINTER(aIsPending)do { if ((__builtin_expect(!!(!(aIsPending)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aIsPending" ") failed",
nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 464); return NS_ERROR_INVALID_POINTER; } } while (false)
;
465 *aIsPending = LoadIsPending() || LoadForcePending();
466 return NS_OK;
467}
468
469NS_IMETHODIMPnsresult
470HttpBaseChannel::GetStatus(nsresult* aStatus) {
471 NS_ENSURE_ARG_POINTER(aStatus)do { if ((__builtin_expect(!!(!(aStatus)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aStatus" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 471
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
472 *aStatus = mStatus;
473 return NS_OK;
474}
475
476NS_IMETHODIMPnsresult
477HttpBaseChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
478 NS_ENSURE_ARG_POINTER(aLoadGroup)do { if ((__builtin_expect(!!(!(aLoadGroup)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aLoadGroup" ") failed",
nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 478); return NS_ERROR_INVALID_POINTER; } } while (false)
;
479 *aLoadGroup = do_AddRef(mLoadGroup).take();
480 return NS_OK;
481}
482
483NS_IMETHODIMPnsresult
484HttpBaseChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
485 MOZ_ASSERT(NS_IsMainThread(), "Should only 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 only be called on the main thread." ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should only be called on the main thread." ")"); do {
MOZ_CrashSequence(__null, 485); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
486
487 if (!CanSetLoadGroup(aLoadGroup)) {
488 return NS_ERROR_FAILURE;
489 }
490
491 mLoadGroup = aLoadGroup;
492 mProgressSink = nullptr;
493 UpdatePrivateBrowsing();
494 return NS_OK;
495}
496
497NS_IMETHODIMPnsresult
498HttpBaseChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
499 NS_ENSURE_ARG_POINTER(aLoadFlags)do { if ((__builtin_expect(!!(!(aLoadFlags)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aLoadFlags" ") failed",
nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 499); return NS_ERROR_INVALID_POINTER; } } while (false)
;
500 *aLoadFlags = mLoadFlags;
501 return NS_OK;
502}
503
504NS_IMETHODIMPnsresult
505HttpBaseChannel::SetLoadFlags(nsLoadFlags aLoadFlags) {
506 mLoadFlags = aLoadFlags;
507 return NS_OK;
508}
509
510NS_IMETHODIMPnsresult
511HttpBaseChannel::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
512 if (!LoadIsOCSP()) {
513 return GetTRRModeImpl(aTRRMode);
514 }
515
516 nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID"@mozilla.org/network/dns-service;1");
517 nsIDNSService::ResolverMode trrMode = nsIDNSService::MODE_NATIVEONLY;
518 // If this is an OCSP channel, and the global TRR mode is TRR_ONLY (3)
519 // then we set the mode for this channel as TRR_DISABLED_MODE.
520 // We do this to prevent a TRR service channel's OCSP validation from
521 // blocking DNS resolution completely.
522 if (dns && NS_SUCCEEDED(dns->GetCurrentTrrMode(&trrMode))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dns->GetCurrentTrrMode
(&trrMode))), 1)))
&&
523 trrMode == nsIDNSService::MODE_TRRONLY) {
524 *aTRRMode = nsIRequest::TRR_DISABLED_MODE;
525 return NS_OK;
526 }
527
528 return GetTRRModeImpl(aTRRMode);
529}
530
531NS_IMETHODIMPnsresult
532HttpBaseChannel::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
533 return SetTRRModeImpl(aTRRMode);
534}
535
536NS_IMETHODIMPnsresult
537HttpBaseChannel::SetDocshellUserAgentOverride() {
538 RefPtr<dom::BrowsingContext> bc;
539 MOZ_ALWAYS_SUCCEEDS(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))), 1)))
), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 539
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))"
")"); do { MOZ_CrashSequence(__null, 539); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
540 if (!bc) {
541 return NS_OK;
542 }
543
544 nsAutoCString customUserAgent;
545 bc->GetCustomUserAgent(customUserAgent);
546 if (customUserAgent.IsEmpty() || customUserAgent.IsVoid()) {
547 return NS_OK;
548 }
549
550 nsresult rv = SetRequestHeaderInternal(
551 "User-Agent"_ns, customUserAgent, false,
552 nsHttpHeaderArray::eVarietyRequestEnforceDefault);
553 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
554 return rv;
555 }
556
557 return NS_OK;
558}
559
560//-----------------------------------------------------------------------------
561// HttpBaseChannel::nsIChannel
562//-----------------------------------------------------------------------------
563
564NS_IMETHODIMPnsresult
565HttpBaseChannel::GetOriginalURI(nsIURI** aOriginalURI) {
566 NS_ENSURE_ARG_POINTER(aOriginalURI)do { if ((__builtin_expect(!!(!(aOriginalURI)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOriginalURI" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 566); return NS_ERROR_INVALID_POINTER; } } while (false)
;
567 *aOriginalURI = do_AddRef(mOriginalURI).take();
568 return NS_OK;
569}
570
571NS_IMETHODIMPnsresult
572HttpBaseChannel::SetOriginalURI(nsIURI* aOriginalURI) {
573 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 573); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 573, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 573); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 573
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
574
575 NS_ENSURE_ARG_POINTER(aOriginalURI)do { if ((__builtin_expect(!!(!(aOriginalURI)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOriginalURI" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 575); return NS_ERROR_INVALID_POINTER; } } while (false)
;
576 mOriginalURI = aOriginalURI;
577 return NS_OK;
578}
579
580NS_IMETHODIMPnsresult
581HttpBaseChannel::GetURI(nsIURI** aURI) {
582 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 582
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
583 *aURI = do_AddRef(mURI).take();
584 return NS_OK;
585}
586
587NS_IMETHODIMPnsresult
588HttpBaseChannel::GetOwner(nsISupports** aOwner) {
589 NS_ENSURE_ARG_POINTER(aOwner)do { if ((__builtin_expect(!!(!(aOwner)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOwner" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 589
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
590 *aOwner = do_AddRef(mOwner).take();
591 return NS_OK;
592}
593
594NS_IMETHODIMPnsresult
595HttpBaseChannel::SetOwner(nsISupports* aOwner) {
596 mOwner = aOwner;
597 return NS_OK;
598}
599
600NS_IMETHODIMPnsresult
601HttpBaseChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) {
602 MOZ_RELEASE_ASSERT(aLoadInfo, "loadinfo can't be null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo" " (" "loadinfo can't be null"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 602); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aLoadInfo"
") (" "loadinfo can't be null" ")"); do { MOZ_CrashSequence(
__null, 602); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
603 mLoadInfo = aLoadInfo;
604 return NS_OK;
605}
606
607NS_IMETHODIMPnsresult
608HttpBaseChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) {
609 *aLoadInfo = do_AddRef(mLoadInfo).take();
610 return NS_OK;
611}
612
613NS_IMETHODIMPnsresult
614HttpBaseChannel::GetIsDocument(bool* aIsDocument) {
615 return NS_GetIsDocumentChannel(this, aIsDocument);
616}
617
618NS_IMETHODIMPnsresult
619HttpBaseChannel::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks) {
620 *aCallbacks = do_AddRef(mCallbacks).take();
621 return NS_OK;
622}
623
624NS_IMETHODIMPnsresult
625HttpBaseChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
626 MOZ_ASSERT(NS_IsMainThread(), "Should only 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 only be called on the main thread." ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 626); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should only be called on the main thread." ")"); do {
MOZ_CrashSequence(__null, 626); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
627
628 if (!CanSetCallbacks(aCallbacks)) {
629 return NS_ERROR_FAILURE;
630 }
631
632 mCallbacks = aCallbacks;
633 mProgressSink = nullptr;
634
635 UpdatePrivateBrowsing();
636 return NS_OK;
637}
638
639NS_IMETHODIMPnsresult
640HttpBaseChannel::GetContentType(nsACString& aContentType) {
641 if (!mResponseHead) {
642 aContentType.Truncate();
643 return NS_ERROR_NOT_AVAILABLE;
644 }
645
646 mResponseHead->ContentType(aContentType);
647 if (!aContentType.IsEmpty()) {
648 return NS_OK;
649 }
650
651 aContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type");
652 return NS_OK;
653}
654
655NS_IMETHODIMPnsresult
656HttpBaseChannel::SetContentType(const nsACString& aContentType) {
657 if (mListener || LoadWasOpened() || mDummyChannelForCachedResource) {
658 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
659
660 nsAutoCString contentTypeBuf, charsetBuf;
661 bool hadCharset;
662 net_ParseContentType(aContentType, contentTypeBuf, charsetBuf, &hadCharset);
663
664 mResponseHead->SetContentType(contentTypeBuf);
665
666 // take care not to stomp on an existing charset
667 if (hadCharset) mResponseHead->SetContentCharset(charsetBuf);
668
669 } else {
670 // We are being given a content-type hint.
671 bool dummy;
672 net_ParseContentType(aContentType, mContentTypeHint, mContentCharsetHint,
673 &dummy);
674 }
675
676 return NS_OK;
677}
678
679NS_IMETHODIMPnsresult
680HttpBaseChannel::GetContentCharset(nsACString& aContentCharset) {
681 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
682
683 mResponseHead->ContentCharset(aContentCharset);
684 return NS_OK;
685}
686
687NS_IMETHODIMPnsresult
688HttpBaseChannel::SetContentCharset(const nsACString& aContentCharset) {
689 if (mListener) {
690 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
691
692 mResponseHead->SetContentCharset(aContentCharset);
693 } else {
694 // Charset hint
695 mContentCharsetHint = aContentCharset;
696 }
697 return NS_OK;
698}
699
700NS_IMETHODIMPnsresult
701HttpBaseChannel::GetContentDisposition(uint32_t* aContentDisposition) {
702 if (mLoadInfo->GetForceMediaDocument() != ForceMediaDocument::None) {
703 *aContentDisposition = nsIChannel::DISPOSITION_FORCE_INLINE;
704 return NS_OK;
705 }
706
707 // See bug 1658877. If mContentDispositionHint is already
708 // DISPOSITION_ATTACHMENT, it means this channel is created from a
709 // download attribute. In this case, we should prefer the value from the
710 // download attribute rather than the value in content disposition header.
711 // DISPOSITION_FORCE_INLINE is used to explicitly set inline, used by
712 // the pdf reader when loading a attachment pdf without having to
713 // download it.
714 if (mContentDispositionHint == nsIChannel::DISPOSITION_ATTACHMENT ||
715 mContentDispositionHint == nsIChannel::DISPOSITION_FORCE_INLINE) {
716 *aContentDisposition = mContentDispositionHint;
717 return NS_OK;
718 }
719
720 nsresult rv;
721 nsCString header;
722
723 rv = GetContentDispositionHeader(header);
724 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
725 if (mContentDispositionHint == UINT32_MAX(4294967295U)) return rv;
726
727 *aContentDisposition = mContentDispositionHint;
728 return NS_OK;
729 }
730
731 *aContentDisposition = NS_GetContentDispositionFromHeader(header, this);
732 return NS_OK;
733}
734
735NS_IMETHODIMPnsresult
736HttpBaseChannel::SetContentDisposition(uint32_t aContentDisposition) {
737 mContentDispositionHint = aContentDisposition;
738 return NS_OK;
739}
740
741NS_IMETHODIMPnsresult
742HttpBaseChannel::GetContentDispositionFilename(
743 nsAString& aContentDispositionFilename) {
744 aContentDispositionFilename.Truncate();
745 nsresult rv;
746 nsCString header;
747
748 rv = GetContentDispositionHeader(header);
749 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
750 rv = NS_GetFilenameFromDisposition(aContentDispositionFilename, header);
751 }
752
753 // If we failed to get the filename from header, we should use
754 // mContentDispositionFilename, since mContentDispositionFilename is set from
755 // the download attribute.
756 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
757 if (!mContentDispositionFilename) {
758 return rv;
759 }
760
761 aContentDispositionFilename = *mContentDispositionFilename;
762 return NS_OK;
763 }
764
765 return rv;
766}
767
768NS_IMETHODIMPnsresult
769HttpBaseChannel::SetContentDispositionFilename(
770 const nsAString& aContentDispositionFilename) {
771 mContentDispositionFilename =
772 MakeUnique<nsString>(aContentDispositionFilename);
773
774 // For safety reasons ensure the filename doesn't contain null characters and
775 // replace them with underscores. We may later pass the extension to system
776 // MIME APIs that expect null terminated strings.
777 mContentDispositionFilename->ReplaceChar(char16_t(0), '_');
778
779 return NS_OK;
780}
781
782NS_IMETHODIMPnsresult
783HttpBaseChannel::GetContentDispositionHeader(
784 nsACString& aContentDispositionHeader) {
785 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
786
787 nsresult rv = mResponseHead->GetHeader(nsHttp::Content_Disposition,
788 aContentDispositionHeader);
789 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || aContentDispositionHeader.IsEmpty()) {
790 return NS_ERROR_NOT_AVAILABLE;
791 }
792
793 return NS_OK;
794}
795
796NS_IMETHODIMPnsresult
797HttpBaseChannel::GetContentLength(int64_t* aContentLength) {
798 NS_ENSURE_ARG_POINTER(aContentLength)do { if ((__builtin_expect(!!(!(aContentLength)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aContentLength" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 798); return NS_ERROR_INVALID_POINTER; } } while (false)
;
799
800 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
801
802 if (LoadDeliveringAltData()) {
803 MOZ_ASSERT(!mAvailableCachedAltDataType.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAvailableCachedAltDataType.IsEmpty())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mAvailableCachedAltDataType.IsEmpty()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mAvailableCachedAltDataType.IsEmpty()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 803
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAvailableCachedAltDataType.IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 803); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
804 *aContentLength = mAltDataLength;
805 return NS_OK;
806 }
807
808 *aContentLength = mResponseHead->ContentLength();
809 return NS_OK;
810}
811
812NS_IMETHODIMPnsresult
813HttpBaseChannel::SetContentLength(int64_t value) {
814 if (!mDummyChannelForCachedResource) {
815 MOZ_ASSERT_UNREACHABLE("HttpBaseChannel::SetContentLength")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: "
"HttpBaseChannel::SetContentLength" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "HttpBaseChannel::SetContentLength"
")"); do { MOZ_CrashSequence(__null, 815); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
816 return NS_ERROR_NOT_IMPLEMENTED;
817 }
818 MOZ_ASSERT(mResponseHead)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mResponseHead)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mResponseHead))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mResponseHead",
"./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 818
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead" ")"
); do { MOZ_CrashSequence(__null, 818); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
819 mResponseHead->SetContentLength(value);
820 return NS_OK;
821}
822
823NS_IMETHODIMPnsresult
824HttpBaseChannel::Open(nsIInputStream** aStream) {
825 if (!gHttpHandler->Active()) {
826 LOG(("HttpBaseChannel::Open 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
, "HttpBaseChannel::Open after HTTP shutdown..."); } } while (
0)
;
827 return NS_ERROR_NOT_AVAILABLE;
828 }
829
830 nsCOMPtr<nsIStreamListener> listener;
831 nsresult rv =
832 nsContentSecurityManager::doContentSecurityCheck(this, listener);
833 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 833); return rv; } } while (false)
;
834
835 NS_ENSURE_TRUE(!LoadWasOpened(), NS_ERROR_IN_PROGRESS)do { if ((__builtin_expect(!!(!(!LoadWasOpened())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadWasOpened()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 835); return NS_ERROR_IN_PROGRESS; } } while (false)
;
836
837 if (!gHttpHandler->Active()) {
838 LOG(("HttpBaseChannel::Open 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
, "HttpBaseChannel::Open after HTTP shutdown..."); } } while (
0)
;
839 return NS_ERROR_NOT_AVAILABLE;
840 }
841
842 return NS_ImplementChannelOpen(this, aStream);
843}
844
845NS_IMETHODIMPnsresult
846HttpBaseChannel::GetParentProcessChannelHandle(
847 mozilla::dom::ParentProcessChannelHandle** aValue) {
848 *aValue = do_AddRef(mParentProcessChannelHandle).take();
849 return NS_OK;
850}
851
852NS_IMETHODIMPnsresult
853HttpBaseChannel::SetParentProcessChannelHandle(
854 mozilla::dom::ParentProcessChannelHandle* aValue) {
855 if (XRE_IsParentProcess()) {
856 MOZ_ASSERT_UNREACHABLE(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: "
"SetParentProcessChannelHandle in the parent process would leak"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "SetParentProcessChannelHandle in the parent process would leak"
")"); do { MOZ_CrashSequence(__null, 857); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
857 "SetParentProcessChannelHandle in the parent process would leak")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: "
"SetParentProcessChannelHandle in the parent process would leak"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "SetParentProcessChannelHandle in the parent process would leak"
")"); do { MOZ_CrashSequence(__null, 857); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
858 return NS_ERROR_NOT_AVAILABLE;
859 }
860
861 mParentProcessChannelHandle = aValue;
862 return NS_OK;
863}
864
865//-----------------------------------------------------------------------------
866// HttpBaseChannel::nsIUploadChannel
867//-----------------------------------------------------------------------------
868
869NS_IMETHODIMPnsresult
870HttpBaseChannel::GetUploadStream(nsIInputStream** stream) {
871 NS_ENSURE_ARG_POINTER(stream)do { if ((__builtin_expect(!!(!(stream)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stream" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 871
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
872 *stream = do_AddRef(mUploadStream).take();
873 return NS_OK;
874}
875
876NS_IMETHODIMPnsresult
877HttpBaseChannel::SetUploadStream(nsIInputStream* stream,
878 const nsACString& contentTypeArg,
879 int64_t contentLength) {
880 // NOTE: for backwards compatibility and for compatibility with old style
881 // plugins, |stream| may include headers, specifically Content-Type and
882 // Content-Length headers. in this case, |contentType| and |contentLength|
883 // would be unspecified. this is traditionally the case of a POST request,
884 // and so we select POST as the request method if contentType and
885 // contentLength are unspecified.
886
887 if (stream) {
888 nsAutoCString method;
889
890 // This method and ExplicitSetUploadStream mean different things by "empty
891 // content type string". This method means "no header", but
892 // ExplicitSetUploadStream means "header with empty value". So we have to
893 // massage the contentType argument into the form ExplicitSetUploadStream
894 // expects.
895 nsCOMPtr<nsIMIMEInputStream> mimeStream;
896 nsCString contentType(contentTypeArg);
897 if (contentType.IsEmpty()) {
898 contentType.SetIsVoid(true);
899 method = "POST"_ns;
900
901 // MIME streams are a special case, and include headers which need to be
902 // copied to the channel.
903 mimeStream = do_QueryInterface(stream);
904 if (mimeStream) {
905 // Copy non-origin related headers to the channel.
906 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
907 new AddHeadersToChannelVisitor(this);
908 mimeStream->VisitHeaders(visitor);
909
910 return ExplicitSetUploadStream(stream, contentType, contentLength,
911 method);
912 }
913 } else {
914 method = "PUT"_ns;
915
916 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(CallQueryInterface
(stream, getter_AddRefs(mimeStream)))), 0))))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(((bool)(__builtin_expect(!!(
NS_FAILED_impl(CallQueryInterface(stream, getter_AddRefs(mimeStream
)))), 0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(NS_FAILED_impl(CallQueryInterface(stream, getter_AddRefs(mimeStream)))), 0)))"
" (" "nsIMIMEInputStream should not be set with an explicit content type"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(CallQueryInterface(stream, getter_AddRefs(mimeStream)))), 0)))"
") (" "nsIMIMEInputStream should not be set with an explicit content type"
")"); do { MOZ_CrashSequence(__null, 918); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
917 NS_FAILED(CallQueryInterface(stream, getter_AddRefs(mimeStream))),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(CallQueryInterface
(stream, getter_AddRefs(mimeStream)))), 0))))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(((bool)(__builtin_expect(!!(
NS_FAILED_impl(CallQueryInterface(stream, getter_AddRefs(mimeStream
)))), 0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(NS_FAILED_impl(CallQueryInterface(stream, getter_AddRefs(mimeStream)))), 0)))"
" (" "nsIMIMEInputStream should not be set with an explicit content type"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(CallQueryInterface(stream, getter_AddRefs(mimeStream)))), 0)))"
") (" "nsIMIMEInputStream should not be set with an explicit content type"
")"); do { MOZ_CrashSequence(__null, 918); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
918 "nsIMIMEInputStream should not be set with an explicit content type")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(CallQueryInterface
(stream, getter_AddRefs(mimeStream)))), 0))))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(((bool)(__builtin_expect(!!(
NS_FAILED_impl(CallQueryInterface(stream, getter_AddRefs(mimeStream
)))), 0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(NS_FAILED_impl(CallQueryInterface(stream, getter_AddRefs(mimeStream)))), 0)))"
" (" "nsIMIMEInputStream should not be set with an explicit content type"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(CallQueryInterface(stream, getter_AddRefs(mimeStream)))), 0)))"
") (" "nsIMIMEInputStream should not be set with an explicit content type"
")"); do { MOZ_CrashSequence(__null, 918); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
919 }
920 return ExplicitSetUploadStream(stream, contentType, contentLength, method);
921 }
922
923 // if stream is null, ExplicitSetUploadStream returns error.
924 // So we need special case for GET method.
925 SetRequestMethod("GET"_ns); // revert to GET request
926 mUploadStream = nullptr;
927 return NS_OK;
928}
929
930namespace {
931
932class MIMEHeaderCopyVisitor final : public nsIHttpHeaderVisitor {
933 public:
934 explicit MIMEHeaderCopyVisitor(nsIMIMEInputStream* aDest) : mDest(aDest) {}
935
936 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:
937 NS_IMETHODvirtual nsresult VisitHeader(const nsACString& aName,
938 const nsACString& aValue) override {
939 return mDest->AddHeader(PromiseFlatCStringTPromiseFlatString<char>(aName).get(),
940 PromiseFlatCStringTPromiseFlatString<char>(aValue).get());
941 }
942
943 private:
944 ~MIMEHeaderCopyVisitor() = default;
945
946 nsCOMPtr<nsIMIMEInputStream> mDest;
947};
948
949NS_IMPL_ISUPPORTS(MIMEHeaderCopyVisitor, nsIHttpHeaderVisitor)MozExternalRefCountType MIMEHeaderCopyVisitor::AddRef(void) {
static_assert(!std::is_destructible_v<MIMEHeaderCopyVisitor
>, "Reference-counted class " "MIMEHeaderCopyVisitor" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 949); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 949
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("MIMEHeaderCopyVisitor" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("MIMEHeaderCopyVisitor" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"MIMEHeaderCopyVisitor\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 949); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MIMEHeaderCopyVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 949); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("MIMEHeaderCopyVisitor" " not thread-safe"); nsrefcnt count =
++mRefCnt; NS_LogAddRef((this), (count), ("MIMEHeaderCopyVisitor"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
MIMEHeaderCopyVisitor::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 949); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 949
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("MIMEHeaderCopyVisitor" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("MIMEHeaderCopyVisitor" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"MIMEHeaderCopyVisitor\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 949); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MIMEHeaderCopyVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 949); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("MIMEHeaderCopyVisitor" " not thread-safe"); const char* const
nametmp = "MIMEHeaderCopyVisitor"; nsrefcnt count = --mRefCnt
; NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; } nsresult
MIMEHeaderCopyVisitor::QueryInterface(const nsIID& aIID,
void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 949); 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<MIMEHeaderCopyVisitor, nsIHttpHeaderVisitor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIHttpHeaderVisitor
*>((MIMEHeaderCopyVisitor*)0x1000)) - reinterpret_cast<
char*>((MIMEHeaderCopyVisitor*)0x1000))}, {&mozilla::detail
::kImplementedIID<MIMEHeaderCopyVisitor, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIHttpHeaderVisitor*>((MIMEHeaderCopyVisitor
*)0x1000))) - reinterpret_cast<char*>((MIMEHeaderCopyVisitor
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
950
951static void NormalizeCopyComplete(void* aClosure, nsresult aStatus) {
952#ifdef DEBUG1
953 // Called on the STS thread by NS_AsyncCopy
954 nsCOMPtr<nsIEventTarget> sts =
955 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID"@mozilla.org/network/stream-transport-service;1");
956 bool result = false;
957 sts->IsOnCurrentThread(&result);
958 MOZ_ASSERT(result, "Should only be called on the STS thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(result)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(result))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("result" " (" "Should only be called on the STS thread."
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "result" ") ("
"Should only be called on the STS thread." ")"); do { MOZ_CrashSequence
(__null, 958); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
959#endif
960
961 RefPtr<GenericPromise::Private> ready =
962 already_AddRefed(static_cast<GenericPromise::Private*>(aClosure));
963 if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
964 ready->Resolve(true, __func__);
965 } else {
966 ready->Reject(aStatus, __func__);
967 }
968}
969
970// Normalize the upload stream for a HTTP channel, so that is one of the
971// expected and compatible types. Components like WebExtensions and DevTools
972// expect that upload streams in the parent process are cloneable, seekable, and
973// synchronous to read, which this function helps guarantee somewhat efficiently
974// and without loss of information.
975//
976// If the replacement stream outparameter is not initialized to `nullptr`, the
977// returned stream should be used instead of `aUploadStream` as the upload
978// stream for the HTTP channel, and the previous stream should not be touched
979// again.
980//
981// If aReadyPromise is non-nullptr after the function is called, it is a promise
982// which should be awaited before continuing to `AsyncOpen` the HTTP channel,
983// as the replacement stream will not be ready until it is resolved.
984static nsresult NormalizeUploadStream(nsIInputStream* aUploadStream,
985 nsIInputStream** aReplacementStream,
986 GenericPromise** aReadyPromise) {
987 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 987
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 987); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
988
989 *aReplacementStream = nullptr;
990 *aReadyPromise = nullptr;
991
992 // Unwrap RemoteLazyInputStream and normalize the contents as we're in the
993 // parent process.
994 if (nsCOMPtr<mozIRemoteLazyInputStream> lazyStream =
995 do_QueryInterface(aUploadStream)) {
996 nsCOMPtr<nsIInputStream> internal;
997 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(lazyStream->TakeInternalStream
(getter_AddRefs(internal)))), 1)))
998 lazyStream->TakeInternalStream(getter_AddRefs(internal)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(lazyStream->TakeInternalStream
(getter_AddRefs(internal)))), 1)))
) {
999 nsCOMPtr<nsIInputStream> replacement;
1000 nsresult rv = NormalizeUploadStream(internal, getter_AddRefs(replacement),
1001 aReadyPromise);
1002 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1002); return rv; } } while (false)
;
1003
1004 if (replacement) {
1005 replacement.forget(aReplacementStream);
1006 } else {
1007 internal.forget(aReplacementStream);
1008 }
1009 return NS_OK;
1010 }
1011 }
1012
1013 // Preserve MIME information on the stream when normalizing.
1014 if (nsCOMPtr<nsIMIMEInputStream> mime = do_QueryInterface(aUploadStream)) {
1015 nsCOMPtr<nsIInputStream> data;
1016 nsresult rv = mime->GetData(getter_AddRefs(data));
1017 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1017); return rv; } } while (false)
;
1018
1019 nsCOMPtr<nsIInputStream> replacement;
1020 rv =
1021 NormalizeUploadStream(data, getter_AddRefs(replacement), aReadyPromise);
1022 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1022); return rv; } } while (false)
;
1023
1024 if (replacement) {
1025 nsCOMPtr<nsIMIMEInputStream> replacementMime(
1026 do_CreateInstance("@mozilla.org/network/mime-input-stream;1", &rv));
1027 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1027); return rv; } } while (false)
;
1028
1029 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
1030 new MIMEHeaderCopyVisitor(replacementMime);
1031 rv = mime->VisitHeaders(visitor);
1032 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1032); return rv; } } while (false)
;
1033
1034 rv = replacementMime->SetData(replacement);
1035 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1035); return rv; } } while (false)
;
1036
1037 replacementMime.forget(aReplacementStream);
1038 }
1039 return NS_OK;
1040 }
1041
1042 // Preserve "real" buffered input streams which wrap data (i.e. are backed by
1043 // nsBufferedInputStream), but normalize the wrapped stream.
1044 if (nsCOMPtr<nsIBufferedInputStream> buffered =
1045 do_QueryInterface(aUploadStream)) {
1046 nsCOMPtr<nsIInputStream> data;
1047 if (NS_SUCCEEDED(buffered->GetData(getter_AddRefs(data)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(buffered->GetData
(getter_AddRefs(data)))), 1)))
) {
1048 nsCOMPtr<nsIInputStream> replacement;
1049 nsresult rv = NormalizeUploadStream(data, getter_AddRefs(replacement),
1050 aReadyPromise);
1051 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1051); return rv; } } while (false)
;
1052 if (replacement) {
1053 // This buffer size should be kept in sync with HTMLFormSubmission.
1054 rv = NS_NewBufferedInputStream(aReplacementStream, replacement.forget(),
1055 8192);
1056 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1056); return rv; } } while (false)
;
1057 }
1058 return NS_OK;
1059 }
1060 }
1061
1062 // Preserve multiplex input streams, normalizing each individual inner stream
1063 // to avoid unnecessary copying.
1064 if (nsCOMPtr<nsIMultiplexInputStream> multiplex =
1065 do_QueryInterface(aUploadStream)) {
1066 uint32_t count = multiplex->GetCount();
1067 nsTArray<nsCOMPtr<nsIInputStream>> streams(count);
1068 nsTArray<RefPtr<GenericPromise>> promises(count);
1069 bool replace = false;
1070 for (uint32_t i = 0; i < count; ++i) {
1071 nsCOMPtr<nsIInputStream> inner;
1072 nsresult rv = multiplex->GetStream(i, getter_AddRefs(inner));
1073 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1073); return rv; } } while (false)
;
1074
1075 RefPtr<GenericPromise> promise;
1076 nsCOMPtr<nsIInputStream> replacement;
1077 rv = NormalizeUploadStream(inner, getter_AddRefs(replacement),
1078 getter_AddRefs(promise));
1079 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1079); return rv; } } while (false)
;
1080 if (promise) {
1081 promises.AppendElement(promise);
1082 }
1083 if (replacement) {
1084 streams.AppendElement(replacement);
1085 replace = true;
1086 } else {
1087 streams.AppendElement(inner);
1088 }
1089 }
1090
1091 // If any of the inner streams needed to be replaced, replace the entire
1092 // nsIMultiplexInputStream.
1093 if (replace) {
1094 nsresult rv;
1095 nsCOMPtr<nsIMultiplexInputStream> replacement =
1096 do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1", &rv);
1097 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1097); return rv; } } while (false)
;
1098 for (auto& stream : streams) {
1099 rv = replacement->AppendStream(stream);
1100 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1100); return rv; } } while (false)
;
1101 }
1102
1103 MOZ_ALWAYS_SUCCEEDS(CallQueryInterface(replacement, aReplacementStream))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(CallQueryInterface(replacement, aReplacementStream))), 1))))
, 1))) { } else { do { do { } while (false); MOZ_ReportCrash(
"" "NS_SUCCEEDED(CallQueryInterface(replacement, aReplacementStream))"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1103
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(CallQueryInterface(replacement, aReplacementStream))"
")"); do { MOZ_CrashSequence(__null, 1103); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1104 }
1105
1106 // Wait for all inner promises to settle before resolving the final promise.
1107 if (!promises.IsEmpty()) {
1108 RefPtr<GenericPromise> ready =
1109 GenericPromise::AllSettled(GetCurrentSerialEventTarget(), promises)
1110 ->Then(GetCurrentSerialEventTarget(), __func__,
1111 [](GenericPromise::AllSettledPromiseType::
1112 ResolveOrRejectValue&& aResults)
1113 -> RefPtr<GenericPromise> {
1114 MOZ_ASSERT(aResults.IsResolve(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aResults.IsResolve())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aResults.IsResolve()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aResults.IsResolve()"
" (" "AllSettled never rejects" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aResults.IsResolve()"
") (" "AllSettled never rejects" ")"); do { MOZ_CrashSequence
(__null, 1115); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1115 "AllSettled never rejects")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aResults.IsResolve())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aResults.IsResolve()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aResults.IsResolve()"
" (" "AllSettled never rejects" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aResults.IsResolve()"
") (" "AllSettled never rejects" ")"); do { MOZ_CrashSequence
(__null, 1115); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1116 for (auto& result : aResults.ResolveValue()) {
1117 if (result.IsReject()) {
1118 return GenericPromise::CreateAndReject(
1119 result.RejectValue(), __func__);
1120 }
1121 }
1122 return GenericPromise::CreateAndResolve(true, __func__);
1123 });
1124 ready.forget(aReadyPromise);
1125 }
1126 return NS_OK;
1127 }
1128
1129 // If the stream is cloneable, seekable and non-async, we can allow it. Async
1130 // input streams can cause issues, as various consumers of input streams
1131 // expect the payload to be synchronous and `Available()` to be the length of
1132 // the stream, which is not true for asynchronous streams.
1133 nsCOMPtr<nsIAsyncInputStream> async = do_QueryInterface(aUploadStream);
1134 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(aUploadStream);
1135 if (NS_InputStreamIsCloneable(aUploadStream) && seekable && !async) {
1136 return NS_OK;
1137 }
1138
1139 // Asynchronously copy our non-normalized stream into a StorageStream so that
1140 // it is seekable, cloneable, and synchronous once the copy completes.
1141
1142 NS_WARNING("Upload Stream is being copied into StorageStream")NS_DebugBreak(NS_DEBUG_WARNING, "Upload Stream is being copied into StorageStream"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1142)
;
1143
1144 // nsStorageStream requires a power-of-two segment size.
1145 static constexpr uint32_t kMinCopySegmentSize = 4 * 1024;
1146 static constexpr uint32_t kMaxCopySegmentSize = 1u << 31;
1147 const uint32_t maxCopySegmentSize = RoundUpPow2(
1148 std::clamp(StaticPrefs::network_http_upload_copy_max_segment_size(),
1149 kMinCopySegmentSize, kMaxCopySegmentSize));
1150 uint32_t segmentSize = maxCopySegmentSize;
1151 int64_t length;
1152 if (InputStreamLengthHelper::GetSyncLength(aUploadStream, &length) &&
1153 length >= 0) {
1154 segmentSize = RoundUpPow2(
1155 std::clamp<int64_t>(length, kMinCopySegmentSize, maxCopySegmentSize));
1156 }
1157
1158 nsCOMPtr<nsIStorageStream> storageStream;
1159 nsresult rv = NS_NewStorageStream(segmentSize, UINT32_MAX(4294967295U),
1160 getter_AddRefs(storageStream));
1161 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1161); return rv; } } while (false)
;
1162
1163 nsCOMPtr<nsIOutputStream> sink;
1164 rv = storageStream->GetOutputStream(0, getter_AddRefs(sink));
1165 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1165); return rv; } } while (false)
;
1166
1167 nsCOMPtr<nsIInputStream> replacementStream;
1168 rv = storageStream->NewInputStream(0, getter_AddRefs(replacementStream));
1169 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1169); return rv; } } while (false)
;
1170
1171 // Ensure the source stream is buffered before starting the copy so we can use
1172 // ReadSegments, as nsStorageStream doesn't implement WriteSegments.
1173 nsCOMPtr<nsIInputStream> source = aUploadStream;
1174 if (!NS_InputStreamIsBuffered(aUploadStream)) {
1175 nsCOMPtr<nsIInputStream> bufferedSource;
1176 rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedSource),
1177 source.forget(), segmentSize);
1178 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1178); return rv; } } while (false)
;
1179 source = bufferedSource.forget();
1180 }
1181
1182 // Perform an AsyncCopy into the input stream on the STS.
1183 nsCOMPtr<nsIEventTarget> target =
1184 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID"@mozilla.org/network/stream-transport-service;1");
1185 RefPtr<GenericPromise::Private> ready = new GenericPromise::Private(__func__);
1186 rv =
1187 NS_AsyncCopy(source, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
1188 segmentSize, NormalizeCopyComplete, do_AddRef(ready).take());
1189 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1189)
) {
1190 ready.get()->Release();
1191 return rv;
1192 }
1193
1194 replacementStream.forget(aReplacementStream);
1195 ready.forget(aReadyPromise);
1196 return NS_OK;
1197}
1198
1199} // anonymous namespace
1200
1201NS_IMETHODIMPnsresult
1202HttpBaseChannel::CloneUploadStream(int64_t* aContentLength,
1203 nsIInputStream** aClonedStream) {
1204 NS_ENSURE_ARG_POINTER(aContentLength)do { if ((__builtin_expect(!!(!(aContentLength)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aContentLength" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1204); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1205 NS_ENSURE_ARG_POINTER(aClonedStream)do { if ((__builtin_expect(!!(!(aClonedStream)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aClonedStream" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1205); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1206 *aClonedStream = nullptr;
1207
1208 if (!XRE_IsParentProcess()) {
1209 NS_WARNING("CloneUploadStream is only supported in the parent process")NS_DebugBreak(NS_DEBUG_WARNING, "CloneUploadStream is only supported in the parent process"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1209)
;
1210 return NS_ERROR_NOT_AVAILABLE;
1211 }
1212
1213 if (!mUploadStream) {
1214 return NS_OK;
1215 }
1216
1217 // Teeing an async pipe would buffer an upload of unbounded size in memory,
1218 // so report no clone.
1219 if (LoadUploadStreamIsStreaming()) {
1220 *aContentLength = -1;
1221 return NS_OK;
1222 }
1223
1224 nsCOMPtr<nsIInputStream> clonedStream;
1225 nsresult rv =
1226 NS_CloneInputStream(mUploadStream, getter_AddRefs(clonedStream));
1227 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1227); return rv; } } while (false)
;
1228
1229 clonedStream.forget(aClonedStream);
1230
1231 *aContentLength = mReqContentLength;
1232 return NS_OK;
1233}
1234
1235//-----------------------------------------------------------------------------
1236// HttpBaseChannel::nsIUploadChannel2
1237//-----------------------------------------------------------------------------
1238
1239NS_IMETHODIMPnsresult
1240HttpBaseChannel::ExplicitSetUploadStream(nsIInputStream* aStream,
1241 const nsACString& aContentType,
1242 int64_t aContentLength,
1243 const nsACString& aMethod) {
1244 // Ensure stream is set and method is valid
1245 NS_ENSURE_TRUE(aStream, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aStream)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aStream" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1245
); return NS_ERROR_FAILURE; } } while (false)
;
1246
1247 nsresult rv = SetRequestMethod(aMethod);
1248 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1248); return rv; } } while (false)
;
1249
1250 if (!aContentType.IsVoid()) {
1251 if (aContentType.IsEmpty()) {
1252 SetEmptyRequestHeader("Content-Type"_ns);
1253 } else {
1254 SetRequestHeader("Content-Type"_ns, aContentType, false);
1255 }
1256 }
1257
1258 return InternalSetUploadStream(aStream, aContentLength, true);
1259}
1260
1261nsresult HttpBaseChannel::InternalSetUploadStream(
1262 nsIInputStream* aUploadStream, int64_t aContentLength,
1263 bool aSetContentLengthHeader) {
1264 // If we're not on the main thread, such as for TRR, the content length must
1265 // be provided, as we can't normalize our upload stream.
1266 if (!NS_IsMainThread()) {
1267 if (aContentLength < 0) {
1268 MOZ_ASSERT_UNREACHABLE(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: "
"Upload content length must be explicit off-main-thread" ")"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1269
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Upload content length must be explicit off-main-thread" ")"
); do { MOZ_CrashSequence(__null, 1269); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1269 "Upload content length must be explicit off-main-thread")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: "
"Upload content length must be explicit off-main-thread" ")"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1269
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Upload content length must be explicit off-main-thread" ")"
); do { MOZ_CrashSequence(__null, 1269); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1270 return NS_ERROR_INVALID_ARG;
1271 }
1272
1273 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(aUploadStream);
1274 if (!NS_InputStreamIsCloneable(aUploadStream) || !seekable) {
1275 MOZ_ASSERT_UNREACHABLE(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: "
"Upload stream must be cloneable & seekable off-main-thread"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Upload stream must be cloneable & seekable off-main-thread"
")"); do { MOZ_CrashSequence(__null, 1276); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1276 "Upload stream must be cloneable & seekable off-main-thread")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: "
"Upload stream must be cloneable & seekable off-main-thread"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Upload stream must be cloneable & seekable off-main-thread"
")"); do { MOZ_CrashSequence(__null, 1276); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1277 return NS_ERROR_INVALID_ARG;
1278 }
1279
1280 mUploadStream = aUploadStream;
1281 ExplicitSetUploadStreamLength(aContentLength, aSetContentLengthHeader);
1282 return NS_OK;
1283 }
1284
1285 // For streaming uploads (JS ReadableStream body), the stream is an async
1286 // pipe fed by FetchStreamReader. It cannot be normalized (buffered into a
1287 // StorageStream) because it's consumed incrementally. Skip normalization
1288 // entirely and use the pipe as-is.
1289 if (LoadUploadStreamIsStreaming()) {
1290 mUploadStream = aUploadStream;
1291 // mReqContentLength stays 0: the length genuinely is not known yet.
1292 // nsHttpTransaction::Init consults RequestBodyIsStreaming() so that it
1293 // does not mistake that for "no body".
1294 return NS_OK;
1295 }
1296
1297 // Normalize the upload stream we're provided to ensure that it is cloneable,
1298 // seekable, and synchronous when in the parent process.
1299 //
1300 // This might be an async operation, in which case ready will be returned and
1301 // resolved when the operation is complete.
1302 nsCOMPtr<nsIInputStream> replacement;
1303 RefPtr<GenericPromise> ready;
1304 if (XRE_IsParentProcess()) {
1305 nsresult rv = NormalizeUploadStream(
1306 aUploadStream, getter_AddRefs(replacement), getter_AddRefs(ready));
1307 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1307); return rv; } } while (false)
;
1308 }
1309
1310 mUploadStream = replacement ? replacement.get() : aUploadStream;
1311
1312 // Once the upload stream is ready, fetch its length before proceeding with
1313 // AsyncOpen.
1314 auto onReady = [self = RefPtr{this}, aContentLength, aSetContentLengthHeader,
1315 stream = mUploadStream]() {
1316 auto setLengthAndResume = [self, aSetContentLengthHeader](int64_t aLength) {
1317 self->StorePendingUploadStreamNormalization(false);
1318 self->ExplicitSetUploadStreamLength(aLength >= 0 ? aLength : 0,
1319 aSetContentLengthHeader);
1320 self->MaybeResumeAsyncOpen();
1321 };
1322
1323 if (aContentLength >= 0) {
1324 setLengthAndResume(aContentLength);
1325 return;
1326 }
1327
1328 int64_t length;
1329 if (InputStreamLengthHelper::GetSyncLength(stream, &length)) {
1330 setLengthAndResume(length);
1331 return;
1332 }
1333
1334 InputStreamLengthHelper::GetAsyncLength(stream, setLengthAndResume);
1335 };
1336 StorePendingUploadStreamNormalization(true);
1337
1338 // Resolve onReady synchronously unless a promise is returned.
1339 if (ready) {
1340 ready->Then(GetCurrentSerialEventTarget(), __func__,
1341 [onReady = std::move(onReady)](
1342 GenericPromise::ResolveOrRejectValue&&) { onReady(); });
1343 } else {
1344 onReady();
1345 }
1346 return NS_OK;
1347}
1348
1349void HttpBaseChannel::ExplicitSetUploadStreamLength(
1350 uint64_t aContentLength, bool aSetContentLengthHeader) {
1351 // We already have the content length. We don't need to determinate it.
1352 mReqContentLength = aContentLength;
1353
1354 if (!aSetContentLengthHeader) {
1355 return;
1356 }
1357
1358 nsAutoCString header;
1359 header.AssignLiteral("Content-Length");
1360
1361 // Maybe the content-length header has been already set.
1362 nsAutoCString value;
1363 nsresult rv = GetRequestHeader(header, value);
1364 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !value.IsEmpty()) {
1365 return;
1366 }
1367
1368 nsAutoCString contentLengthStr;
1369 contentLengthStr.AppendInt(aContentLength);
1370 SetRequestHeader(header, contentLengthStr, false);
1371}
1372
1373bool HttpBaseChannel::MaybeWaitForUploadStreamNormalization(
1374 nsIStreamListener* aListener, nsISupports* aContext) {
1375 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1375
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 1375); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1376 MOZ_ASSERT(!LoadAsyncOpenWaitingForStreamNormalization(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadAsyncOpenWaitingForStreamNormalization())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!LoadAsyncOpenWaitingForStreamNormalization()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!LoadAsyncOpenWaitingForStreamNormalization()"
" (" "AsyncOpen() called twice?" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadAsyncOpenWaitingForStreamNormalization()"
") (" "AsyncOpen() called twice?" ")"); do { MOZ_CrashSequence
(__null, 1377); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1377 "AsyncOpen() called twice?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadAsyncOpenWaitingForStreamNormalization())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!LoadAsyncOpenWaitingForStreamNormalization()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!LoadAsyncOpenWaitingForStreamNormalization()"
" (" "AsyncOpen() called twice?" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadAsyncOpenWaitingForStreamNormalization()"
") (" "AsyncOpen() called twice?" ")"); do { MOZ_CrashSequence
(__null, 1377); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1378
1379 if (!LoadPendingUploadStreamNormalization()) {
1380 return false;
1381 }
1382
1383 mListener = aListener;
1384 StoreAsyncOpenWaitingForStreamNormalization(true);
1385 return true;
1386}
1387
1388void HttpBaseChannel::MaybeResumeAsyncOpen() {
1389 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1389
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 1389); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1390 MOZ_ASSERT(!LoadPendingUploadStreamNormalization())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadPendingUploadStreamNormalization())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!LoadPendingUploadStreamNormalization()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!LoadPendingUploadStreamNormalization()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1390
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadPendingUploadStreamNormalization()"
")"); do { MOZ_CrashSequence(__null, 1390); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1391
1392 if (!LoadAsyncOpenWaitingForStreamNormalization()) {
1393 return;
1394 }
1395
1396 nsCOMPtr<nsIStreamListener> listener;
1397 listener.swap(mListener);
1398
1399 StoreAsyncOpenWaitingForStreamNormalization(false);
1400
1401 nsresult rv = AsyncOpen(listener);
1402 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1402)
) {
1403 DoAsyncAbort(rv);
1404 }
1405}
1406
1407//-----------------------------------------------------------------------------
1408// HttpBaseChannel::nsIEncodedChannel
1409//-----------------------------------------------------------------------------
1410
1411NS_IMETHODIMPnsresult
1412HttpBaseChannel::GetApplyConversion(bool* value) {
1413 *value = LoadApplyConversion();
1414 return NS_OK;
1415}
1416
1417NS_IMETHODIMPnsresult
1418HttpBaseChannel::SetApplyConversion(bool value) {
1419 LOG(("HttpBaseChannel::SetApplyConversion [this=%p value=%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
, "HttpBaseChannel::SetApplyConversion [this=%p value=%d]\n",
this, value); } } while (0)
1420 value))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetApplyConversion [this=%p value=%d]\n",
this, value); } } while (0)
;
1421 StoreApplyConversion(value);
1422 return NS_OK;
1423}
1424
1425nsresult HttpBaseChannel::DoApplyContentConversions(
1426 nsIStreamListener* aNextListener, nsIStreamListener** aNewNextListener) {
1427 return DoApplyContentConversionsInternal(aNextListener, aNewNextListener,
1428 false, nullptr);
1429}
1430
1431// create a listener chain that looks like this
1432// http-channel -> decompressor (n times) -> InterceptFailedOnSTop ->
1433// channel-creator-listener
1434//
1435// we need to do this because not every decompressor has fully streamed output
1436// so may need a call to OnStopRequest to identify its completion state.. and if
1437// it creates an error there the channel status code needs to be updated before
1438// calling the terminal listener. Having the decompress do it via cancel() means
1439// channels cannot effectively be used in two contexts (specifically this one
1440// and a peek context for sniffing)
1441//
1442class InterceptFailedOnStop : public nsIThreadRetargetableStreamListener {
1443 virtual ~InterceptFailedOnStop() = default;
1444 nsCOMPtr<nsIStreamListener> mNext;
1445 HttpBaseChannel* mChannel;
1446
1447 public:
1448 InterceptFailedOnStop(nsIStreamListener* arg, HttpBaseChannel* chan)
1449 : mNext(arg), mChannel(chan) {}
1450 NS_DECL_THREADSAFE_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::true_type; protected
: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; nsAutoOwningThread
_mOwningThread; public:
1451 NS_DECL_NSITHREADRETARGETABLESTREAMLISTENERvirtual nsresult CheckListenerChain(void) override; virtual nsresult
OnDataFinished(nsresult aStatusCode) override;
1452
1453 NS_IMETHODvirtual nsresult OnStartRequest(nsIRequest* aRequest) override {
1454 nsCOMPtr<nsIStreamListener> next = mNext;
1455 return next->OnStartRequest(aRequest);
1456 }
1457
1458 NS_IMETHODvirtual nsresult OnStopRequest(nsIRequest* aRequest,
1459 nsresult aStatusCode) override {
1460 if (NS_FAILED(aStatusCode)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatusCode)), 0))
)
&& NS_SUCCEEDED(mChannel->mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mChannel->mStatus
)), 1)))
) {
1461 LOG(("HttpBaseChannel::InterceptFailedOnStop %p seting status %" 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
, "HttpBaseChannel::InterceptFailedOnStop %p seting status %"
"x", mChannel, static_cast<uint32_t>(aStatusCode)); } }
while (0)
1462 mChannel, static_cast<uint32_t>(aStatusCode)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::InterceptFailedOnStop %p seting status %"
"x", mChannel, static_cast<uint32_t>(aStatusCode)); } }
while (0)
;
1463 mChannel->mStatus = aStatusCode;
1464 }
1465 nsCOMPtr<nsIStreamListener> next = mNext;
1466 return next->OnStopRequest(aRequest, aStatusCode);
1467 }
1468
1469 NS_IMETHODvirtual nsresult OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream,
1470 uint64_t aOffset, uint32_t aCount) override {
1471 nsCOMPtr<nsIStreamListener> next = mNext;
1472 return next->OnDataAvailable(aRequest, aInputStream, aOffset, aCount);
1473 }
1474};
1475
1476NS_IMPL_ADDREF(InterceptFailedOnStop)MozExternalRefCountType InterceptFailedOnStop::AddRef(void) {
static_assert(!std::is_destructible_v<InterceptFailedOnStop
>, "Reference-counted class " "InterceptFailedOnStop" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 1476
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("InterceptFailedOnStop" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("InterceptFailedOnStop" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"InterceptFailedOnStop\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"InterceptFailedOnStop\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1476); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("InterceptFailedOnStop" " not thread-safe");
nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("InterceptFailedOnStop"
), (uint32_t)(sizeof(*this))); return count; }
1477NS_IMPL_RELEASE(InterceptFailedOnStop)MozExternalRefCountType InterceptFailedOnStop::Release(void) {
do { static_assert( mozilla::detail::AssertionConditionType<
decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1477
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("InterceptFailedOnStop" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("InterceptFailedOnStop" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"InterceptFailedOnStop\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"InterceptFailedOnStop\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1477); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("InterceptFailedOnStop" " not thread-safe");
const char* const nametmp = "InterceptFailedOnStop"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; }
1478
1479NS_INTERFACE_MAP_BEGIN(InterceptFailedOnStop)nsresult InterceptFailedOnStop::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1479); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
1480 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIStreamListener>)) foundInterface
= static_cast<nsIStreamListener*>(this); else
1481 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestObserver>)) foundInterface
= static_cast<nsIRequestObserver*>(this); else
1482 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableStreamListener>
)) foundInterface = static_cast<nsIThreadRetargetableStreamListener
*>(this); else
1483 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequestObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIRequestObserver*>(this
)); else
1484NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::kIID
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::kIID))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 1484); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
1485
1486NS_IMETHODIMPnsresult
1487InterceptFailedOnStop::CheckListenerChain() {
1488 nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
1489 do_QueryInterface(mNext);
1490 if (!listener) {
1491 return NS_ERROR_NO_INTERFACE;
1492 }
1493
1494 return listener->CheckListenerChain();
1495}
1496
1497NS_IMETHODIMPnsresult
1498InterceptFailedOnStop::OnDataFinished(nsresult aStatus) {
1499 nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
1500 do_QueryInterface(mNext);
1501 if (listener) {
1502 return listener->OnDataFinished(aStatus);
1503 }
1504
1505 return NS_OK;
1506}
1507
1508NS_IMETHODIMPnsresult
1509HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener,
1510 nsIStreamListener** aNewNextListener,
1511 nsISupports* aCtxt) {
1512 return DoApplyContentConversionsInternal(aNextListener, aNewNextListener,
1513 false, aCtxt);
1514}
1515
1516nsresult HttpBaseChannel::DoApplyContentConversionsInternal(
1517 nsIStreamListener* aNextListener, nsIStreamListener** aNewNextListener,
1518 bool aRemoveEncodings, nsISupports* aCtxt) {
1519 *aNewNextListener = nullptr;
1520 if (!mResponseHead || !aNextListener) {
1521 return NS_OK;
1522 }
1523
1524 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::DoApplyContentConversions [this=%p], " "removeEncodings=%d\n"
, this, aRemoveEncodings); } } while (0)
1525 ("HttpBaseChannel::DoApplyContentConversions [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
, "HttpBaseChannel::DoApplyContentConversions [this=%p], " "removeEncodings=%d\n"
, this, aRemoveEncodings); } } while (0)
1526 "removeEncodings=%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
, "HttpBaseChannel::DoApplyContentConversions [this=%p], " "removeEncodings=%d\n"
, this, aRemoveEncodings); } } while (0)
1527 this, aRemoveEncodings))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::DoApplyContentConversions [this=%p], " "removeEncodings=%d\n"
, this, aRemoveEncodings); } } while (0)
;
1528
1529#ifdef DEBUG1
1530 {
1531 nsAutoCString contentEncoding;
1532 nsresult rv =
1533 mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
1534 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !contentEncoding.IsEmpty()) {
1535 nsAutoCString newEncoding;
1536 char* cePtr = contentEncoding.BeginWriting();
1537 while (char* val = nsCRT::strtok(cePtr, HTTP_LWS" \t" ",", &cePtr)) {
1538 if (strcmp(val, "dcb") == 0 || strcmp(val, "dcz") == 0) {
1539 MOZ_ASSERT(LoadApplyConversion() && !LoadHasAppliedConversion())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadApplyConversion() && !LoadHasAppliedConversion
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(LoadApplyConversion() && !LoadHasAppliedConversion
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("LoadApplyConversion() && !LoadHasAppliedConversion()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1539
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadApplyConversion() && !LoadHasAppliedConversion()"
")"); do { MOZ_CrashSequence(__null, 1539); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1540 }
1541 }
1542 }
1543 }
1544#endif
1545 // dcb/dcz must be decompressed in the parent process. If we reach here
1546 // in the content process with dcb/dcz, the parent failed to handle it.
1547 if (XRE_IsContentProcess()) {
1548 nsAutoCString contentEncoding;
1549 nsresult rv =
1550 mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
1551 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
1552 contentEncoding.LowerCaseEqualsLiteral("dcz"))) {
1553 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "dcb/dcz Content-Encoding reached the content process"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1554); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "dcb/dcz Content-Encoding reached the content process"
")"); do { MOZ_CrashSequence(__null, 1554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1554 false, "dcb/dcz Content-Encoding reached the content process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "dcb/dcz Content-Encoding reached the content process"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1554); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "dcb/dcz Content-Encoding reached the content process"
")"); do { MOZ_CrashSequence(__null, 1554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1555 return NS_ERROR_INVALID_CONTENT_ENCODING;
1556 }
1557 }
1558
1559 if (!LoadApplyConversion()) {
1560 LOG(("not applying conversion per ApplyConversion\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 applying conversion per ApplyConversion\n"); } } while
(0)
;
1561 return NS_OK;
1562 }
1563
1564 if (LoadHasAppliedConversion()) {
1565 LOG(("not applying conversion because HasAppliedConversion is 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
, "not applying conversion because HasAppliedConversion is true\n"
); } } while (0)
;
1566 return NS_OK;
1567 }
1568
1569 if (LoadDeliveringAltData()) {
1570 MOZ_ASSERT(!mAvailableCachedAltDataType.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAvailableCachedAltDataType.IsEmpty())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mAvailableCachedAltDataType.IsEmpty()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mAvailableCachedAltDataType.IsEmpty()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1570
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAvailableCachedAltDataType.IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1570); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1571 LOG(("not applying conversion because delivering alt-data\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 applying conversion because delivering alt-data\n"); }
} while (0)
;
1572 return NS_OK;
1573 }
1574
1575 nsAutoCString contentEncoding;
1576 nsresult rv =
1577 mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
1578 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || contentEncoding.IsEmpty()) return NS_OK;
1579
1580 nsCOMPtr<nsIStreamListener> nextListener =
1581 new InterceptFailedOnStop(aNextListener, this);
1582
1583 // The encodings are listed in the order they were applied
1584 // (see rfc 2616 section 14.11), so they need to removed in reverse
1585 // order. This is accomplished because the converter chain ends up
1586 // being a stack with the last converter created being the first one
1587 // to accept the raw network data.
1588
1589 char* cePtr = contentEncoding.BeginWriting();
1590 uint32_t count = 0;
1591 while (char* val = nsCRT::strtok(cePtr, HTTP_LWS" \t" ",", &cePtr)) {
1592 if (++count > 16) {
1593 // For compatibility with old code, we will just carry on without
1594 // removing the encodings
1595 LOG(("Too many Content-Encodings. Ignoring remainder.\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Too many Content-Encodings. Ignoring remainder.\n"); } } while
(0)
;
1596 break;
1597 }
1598
1599 if (gHttpHandler->IsAcceptableEncoding(val,
1600 isSecureOrTrustworthyURL(mURI))) {
1601 RefPtr<nsHTTPCompressConv> converter = new nsHTTPCompressConv();
1602 nsAutoCString from(val);
1603 ToLowerCase(from);
1604 rv = converter->AsyncConvertData(from.get(), "uncompressed", nextListener,
1605 aCtxt);
1606 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1607 LOG(("Unexpected failure of AsyncConvertData %s\n", val))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 failure of AsyncConvertData %s\n", val); } } while
(0)
;
1608 return rv;
1609 }
1610
1611 LOG(("Adding converter for content-encoding '%s'", val))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Adding converter for content-encoding '%s'", val); } } while
(0)
;
1612 if (Telemetry::CanRecordPrereleaseData()) {
1613 int mode = 0;
1614 if (from.EqualsLiteral("gzip") || from.EqualsLiteral("x-gzip")) {
1615 mode = 1;
1616 } else if (from.EqualsLiteral("deflate") ||
1617 from.EqualsLiteral("x-deflate")) {
1618 mode = 2;
1619 } else if (from.EqualsLiteral("br")) {
1620 mode = 3;
1621 } else if (from.EqualsLiteral("zstd")) {
1622 mode = 4;
1623 } else if (from.EqualsLiteral("dcb")) {
1624 mode = 5;
1625 } else if (from.EqualsLiteral("dcz")) {
1626 mode = 6;
1627 }
1628 glean::http::content_encoding.AccumulateSingleSample(mode);
1629 }
1630#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
1631 if (from.EqualsLiteral("dcb") || from.EqualsLiteral("dcz")) {
1632 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1632
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 1632); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1633 }
1634#endif
1635 nextListener = converter;
1636 } else {
1637 if (val) {
1638 LOG(("Unknown content encoding '%s'\n", val))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Unknown content encoding '%s'\n", val); } } while (0)
;
1639 }
1640 // we *should* return NS_ERROR_UNEXPECTED here, but that will break sites
1641 // that use things like content-encoding: x-gzip, x-gzip (or any other
1642 // weird encoding)
1643 }
1644 }
1645
1646 // dcb and dcz encodings are removed when it's decompressed (always in
1647 // the parent process). However, in theory you could have
1648 // Content-Encoding: dcb,gzip
1649 // in which case we could pass it down to the content process as
1650 // Content-Encoding: gzip. We won't do that; we'll remove all compressors
1651 // if we need to remove any.
1652 // This double compression of course is silly, but supported by the spec.
1653 if (aRemoveEncodings) {
1654 // If we have dcb or dcz, all content-encodings in the header should be
1655 // removed as we're decompressing before the tee in the parent
1656 // process. Also we should remove any encodings if it's a dictionary
1657 // so we can load it quickly
1658 LOG(("Changing Content-Encoding from '%s' to ''", contentEncoding.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Changing Content-Encoding from '%s' to ''", contentEncoding
.get()); } } while (0)
;
1659 // Can't use SetHeader; we need to overwrite the current value
1660 rv = mResponseHead->SetHeaderOverride(nsHttp::Content_Encoding, ""_ns);
1661 rv = mResponseHead->SetHeaderOverride(nsHttp::Content_Length, ""_ns);
1662 }
1663 *aNewNextListener = do_AddRef(nextListener).take();
1664 return NS_OK;
1665}
1666
1667NS_IMETHODIMPnsresult
1668HttpBaseChannel::GetContentEncodings(nsIUTF8StringEnumerator** aEncodings) {
1669 if (!mResponseHead) {
1670 *aEncodings = nullptr;
1671 return NS_OK;
1672 }
1673
1674 nsAutoCString encoding;
1675 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, encoding);
1676 if (encoding.IsEmpty()) {
1677 *aEncodings = nullptr;
1678 return NS_OK;
1679 }
1680 RefPtr<nsContentEncodings> enumerator =
1681 new nsContentEncodings(this, encoding.get());
1682 enumerator.forget(aEncodings);
1683 return NS_OK;
1684}
1685
1686//-----------------------------------------------------------------------------
1687// HttpBaseChannel::nsContentEncodings <public>
1688//-----------------------------------------------------------------------------
1689
1690HttpBaseChannel::nsContentEncodings::nsContentEncodings(
1691 nsIHttpChannel* aChannel, const char* aEncodingHeader)
1692 : mEncodingHeader(aEncodingHeader), mChannel(aChannel), mReady(false) {
1693 mCurEnd = aEncodingHeader + strlen(aEncodingHeader);
1694 mCurStart = mCurEnd;
1695}
1696
1697//-----------------------------------------------------------------------------
1698// HttpBaseChannel::nsContentEncodings::nsISimpleEnumerator
1699//-----------------------------------------------------------------------------
1700
1701NS_IMETHODIMPnsresult
1702HttpBaseChannel::nsContentEncodings::HasMore(bool* aMoreEncodings) {
1703 if (mReady) {
1704 *aMoreEncodings = true;
1705 return NS_OK;
1706 }
1707
1708 nsresult rv = PrepareForNext();
1709 *aMoreEncodings = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
1710 return NS_OK;
1711}
1712
1713NS_IMETHODIMPnsresult
1714HttpBaseChannel::nsContentEncodings::GetNext(nsACString& aNextEncoding) {
1715 aNextEncoding.Truncate();
1716 if (!mReady) {
1717 nsresult rv = PrepareForNext();
1718 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1719 return NS_ERROR_FAILURE;
1720 }
1721 }
1722
1723 const nsACString& encoding = Substring(mCurStart, mCurEnd);
1724
1725 nsACString::const_iterator start, end;
1726 encoding.BeginReading(start);
1727 encoding.EndReading(end);
1728
1729 bool haveType = false;
1730 if (CaseInsensitiveFindInReadable("gzip"_ns, start, end)) {
1731 aNextEncoding.AssignLiteral(APPLICATION_GZIP"application/x-gzip");
1732 haveType = true;
1733 }
1734
1735 if (!haveType) {
1736 encoding.BeginReading(start);
1737 if (CaseInsensitiveFindInReadable("compress"_ns, start, end)) {
1738 aNextEncoding.AssignLiteral(APPLICATION_COMPRESS"application/x-compress");
1739 haveType = true;
1740 }
1741 }
1742
1743 if (!haveType) {
1744 encoding.BeginReading(start);
1745 if (CaseInsensitiveFindInReadable("deflate"_ns, start, end)) {
1746 aNextEncoding.AssignLiteral(APPLICATION_ZIP"application/zip");
1747 haveType = true;
1748 }
1749 }
1750
1751 if (!haveType) {
1752 encoding.BeginReading(start);
1753 if (CaseInsensitiveFindInReadable("br"_ns, start, end)) {
1754 aNextEncoding.AssignLiteral(APPLICATION_BROTLI"application/brotli");
1755 haveType = true;
1756 }
1757 }
1758
1759 if (!haveType) {
1760 encoding.BeginReading(start);
1761 if (CaseInsensitiveFindInReadable("zstd"_ns, start, end)) {
1762 aNextEncoding.AssignLiteral(APPLICATION_ZSTD"application/zstd");
1763 haveType = true;
1764 }
1765 }
1766
1767 // Prepare to fetch the next encoding
1768 mCurEnd = mCurStart;
1769 mReady = false;
1770
1771 if (haveType) return NS_OK;
1772
1773 NS_WARNING("Unknown encoding type")NS_DebugBreak(NS_DEBUG_WARNING, "Unknown encoding type", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1773
)
;
1774 return NS_ERROR_FAILURE;
1775}
1776
1777//-----------------------------------------------------------------------------
1778// HttpBaseChannel::nsContentEncodings::nsISupports
1779//-----------------------------------------------------------------------------
1780
1781NS_IMPL_ISUPPORTS(HttpBaseChannel::nsContentEncodings, nsIUTF8StringEnumerator,MozExternalRefCountType HttpBaseChannel::nsContentEncodings::
AddRef(void) { static_assert(!std::is_destructible_v<HttpBaseChannel
::nsContentEncodings>, "Reference-counted class " "HttpBaseChannel::nsContentEncodings"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 1782
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("HttpBaseChannel::nsContentEncodings" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("HttpBaseChannel::nsContentEncodings" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"HttpBaseChannel::nsContentEncodings\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel::nsContentEncodings\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1782); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("HttpBaseChannel::nsContentEncodings" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"HttpBaseChannel::nsContentEncodings"), (uint32_t)(sizeof(*this
))); return count; } MozExternalRefCountType HttpBaseChannel::
nsContentEncodings::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1782
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("HttpBaseChannel::nsContentEncodings" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("HttpBaseChannel::nsContentEncodings" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"HttpBaseChannel::nsContentEncodings\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel::nsContentEncodings\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1782); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("HttpBaseChannel::nsContentEncodings" " not thread-safe"
); const char* const nametmp = "HttpBaseChannel::nsContentEncodings"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult HttpBaseChannel::nsContentEncodings
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1782
); 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<HttpBaseChannel::nsContentEncodings, nsIUTF8StringEnumerator
>, int32_t( reinterpret_cast<char*>(static_cast<nsIUTF8StringEnumerator
*>((HttpBaseChannel::nsContentEncodings*)0x1000)) - reinterpret_cast
<char*>((HttpBaseChannel::nsContentEncodings*)0x1000))}
, {&mozilla::detail::kImplementedIID<HttpBaseChannel::
nsContentEncodings, nsIStringEnumerator>, int32_t( reinterpret_cast
<char*>(static_cast<nsIStringEnumerator*>((HttpBaseChannel
::nsContentEncodings*)0x1000)) - reinterpret_cast<char*>
((HttpBaseChannel::nsContentEncodings*)0x1000))}, {&mozilla
::detail::kImplementedIID<HttpBaseChannel::nsContentEncodings
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIUTF8StringEnumerator*
>((HttpBaseChannel::nsContentEncodings*)0x1000))) - reinterpret_cast
<char*>((HttpBaseChannel::nsContentEncodings*)0x1000))}
, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
1782 nsIStringEnumerator)MozExternalRefCountType HttpBaseChannel::nsContentEncodings::
AddRef(void) { static_assert(!std::is_destructible_v<HttpBaseChannel
::nsContentEncodings>, "Reference-counted class " "HttpBaseChannel::nsContentEncodings"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 1782
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("HttpBaseChannel::nsContentEncodings" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("HttpBaseChannel::nsContentEncodings" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"HttpBaseChannel::nsContentEncodings\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel::nsContentEncodings\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1782); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("HttpBaseChannel::nsContentEncodings" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"HttpBaseChannel::nsContentEncodings"), (uint32_t)(sizeof(*this
))); return count; } MozExternalRefCountType HttpBaseChannel::
nsContentEncodings::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1782
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("HttpBaseChannel::nsContentEncodings" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("HttpBaseChannel::nsContentEncodings" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"HttpBaseChannel::nsContentEncodings\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel::nsContentEncodings\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1782); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("HttpBaseChannel::nsContentEncodings" " not thread-safe"
); const char* const nametmp = "HttpBaseChannel::nsContentEncodings"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult HttpBaseChannel::nsContentEncodings
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1782
); 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<HttpBaseChannel::nsContentEncodings, nsIUTF8StringEnumerator
>, int32_t( reinterpret_cast<char*>(static_cast<nsIUTF8StringEnumerator
*>((HttpBaseChannel::nsContentEncodings*)0x1000)) - reinterpret_cast
<char*>((HttpBaseChannel::nsContentEncodings*)0x1000))}
, {&mozilla::detail::kImplementedIID<HttpBaseChannel::
nsContentEncodings, nsIStringEnumerator>, int32_t( reinterpret_cast
<char*>(static_cast<nsIStringEnumerator*>((HttpBaseChannel
::nsContentEncodings*)0x1000)) - reinterpret_cast<char*>
((HttpBaseChannel::nsContentEncodings*)0x1000))}, {&mozilla
::detail::kImplementedIID<HttpBaseChannel::nsContentEncodings
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIUTF8StringEnumerator*
>((HttpBaseChannel::nsContentEncodings*)0x1000))) - reinterpret_cast
<char*>((HttpBaseChannel::nsContentEncodings*)0x1000))}
, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
1783
1784//-----------------------------------------------------------------------------
1785// HttpBaseChannel::nsContentEncodings <private>
1786//-----------------------------------------------------------------------------
1787
1788nsresult HttpBaseChannel::nsContentEncodings::PrepareForNext(void) {
1789 MOZ_ASSERT(mCurStart == mCurEnd, "Indeterminate state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCurStart == mCurEnd)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCurStart == mCurEnd))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("mCurStart == mCurEnd"
" (" "Indeterminate state" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1789); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurStart == mCurEnd"
") (" "Indeterminate state" ")"); do { MOZ_CrashSequence(__null
, 1789); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1790
1791 // At this point both mCurStart and mCurEnd point to somewhere
1792 // past the end of the next thing we want to return
1793
1794 while (mCurEnd != mEncodingHeader) {
1795 --mCurEnd;
1796 if (*mCurEnd != ',' && !nsCRT::IsAsciiSpace(*mCurEnd)) break;
1797 }
1798 if (mCurEnd == mEncodingHeader) {
1799 return NS_ERROR_NOT_AVAILABLE; // no more encodings
1800 }
1801 ++mCurEnd;
1802
1803 // At this point mCurEnd points to the first char _after_ the
1804 // header we want. Furthermore, mCurEnd - 1 != mEncodingHeader
1805
1806 mCurStart = mCurEnd - 1;
1807 while (mCurStart != mEncodingHeader && *mCurStart != ',' &&
1808 !nsCRT::IsAsciiSpace(*mCurStart)) {
1809 --mCurStart;
1810 }
1811 if (*mCurStart == ',' || nsCRT::IsAsciiSpace(*mCurStart)) {
1812 ++mCurStart; // we stopped because of a weird char, so move up one
1813 }
1814
1815 // At this point mCurStart and mCurEnd bracket the encoding string
1816 // we want. Check that it's not "identity"
1817 if (Substring(mCurStart, mCurEnd)
1818 .Equals("identity", nsCaseInsensitiveCStringComparator)) {
1819 mCurEnd = mCurStart;
1820 return PrepareForNext();
1821 }
1822
1823 mReady = true;
1824 return NS_OK;
1825}
1826
1827//-----------------------------------------------------------------------------
1828// HttpBaseChannel::nsIHttpChannel
1829//-----------------------------------------------------------------------------
1830
1831NS_IMETHODIMPnsresult
1832HttpBaseChannel::GetChannelId(uint64_t* aChannelId) {
1833 NS_ENSURE_ARG_POINTER(aChannelId)do { if ((__builtin_expect(!!(!(aChannelId)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChannelId" ") failed",
nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1833); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1834 *aChannelId = mChannelId;
1835 return NS_OK;
1836}
1837
1838NS_IMETHODIMPnsresult
1839HttpBaseChannel::SetChannelId(uint64_t aChannelId) {
1840 mChannelId = aChannelId;
1841 return NS_OK;
1842}
1843
1844NS_IMETHODIMPnsresult HttpBaseChannel::GetTopLevelContentWindowId(uint64_t* aWindowId) {
1845 if (!mContentWindowId) {
1846 nsCOMPtr<nsILoadContext> loadContext;
1847 GetCallback(loadContext);
1848 if (loadContext) {
1849 nsCOMPtr<mozIDOMWindowProxy> topWindow;
1850 loadContext->GetTopWindow(getter_AddRefs(topWindow));
1851 if (topWindow) {
1852 if (nsPIDOMWindowInner* inner =
1853 nsPIDOMWindowOuter::From(topWindow)->GetCurrentInnerWindow()) {
1854 mContentWindowId = inner->WindowID();
1855 }
1856 }
1857 }
1858 }
1859 *aWindowId = mContentWindowId;
1860 return NS_OK;
1861}
1862
1863NS_IMETHODIMPnsresult HttpBaseChannel::SetBrowserId(uint64_t aId) {
1864 mBrowserId = aId;
1865 return NS_OK;
1866}
1867
1868NS_IMETHODIMPnsresult HttpBaseChannel::GetBrowserId(uint64_t* aId) {
1869 EnsureBrowserId();
1870 *aId = mBrowserId;
1871 return NS_OK;
1872}
1873
1874NS_IMETHODIMPnsresult HttpBaseChannel::SetTopLevelContentWindowId(uint64_t aWindowId) {
1875 mContentWindowId = aWindowId;
1876 return NS_OK;
1877}
1878
1879NS_IMETHODIMPnsresult
1880HttpBaseChannel::IsThirdPartyTrackingResource(bool* aIsTrackingResource) {
1881 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags)"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1882
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags)"
")"); do { MOZ_CrashSequence(__null, 1882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1882 !(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags)"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1882
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags)"
")"); do { MOZ_CrashSequence(__null, 1882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1883 *aIsTrackingResource = ChannelClassifierUtils::IsTrackingClassificationFlag(
1884 mThirdPartyClassificationFlags,
1885 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing());
1886 return NS_OK;
1887}
1888
1889NS_IMETHODIMPnsresult
1890HttpBaseChannel::IsThirdPartySocialTrackingResource(
1891 bool* aIsThirdPartySocialTrackingResource) {
1892 MOZ_ASSERT(!mFirstPartyClassificationFlags ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1893
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 1893); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1893 !mThirdPartyClassificationFlags)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1893
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 1893); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1894 *aIsThirdPartySocialTrackingResource =
1895 ChannelClassifierUtils::IsSocialTrackingClassificationFlag(
1896 mThirdPartyClassificationFlags);
1897 return NS_OK;
1898}
1899
1900NS_IMETHODIMPnsresult
1901HttpBaseChannel::GetClassificationFlags(uint32_t* aFlags) {
1902 if (mThirdPartyClassificationFlags) {
1903 *aFlags = mThirdPartyClassificationFlags;
1904 } else {
1905 *aFlags = mFirstPartyClassificationFlags;
1906 }
1907 return NS_OK;
1908}
1909
1910NS_IMETHODIMPnsresult
1911HttpBaseChannel::GetFirstPartyClassificationFlags(uint32_t* aFlags) {
1912 *aFlags = mFirstPartyClassificationFlags;
1913 return NS_OK;
1914}
1915
1916NS_IMETHODIMPnsresult
1917HttpBaseChannel::GetThirdPartyClassificationFlags(uint32_t* aFlags) {
1918 *aFlags = mThirdPartyClassificationFlags;
1919 return NS_OK;
1920}
1921
1922NS_IMETHODIMPnsresult
1923HttpBaseChannel::GetTransferSize(uint64_t* aTransferSize) {
1924 *aTransferSize = mTransferSize;
1925 return NS_OK;
1926}
1927
1928NS_IMETHODIMPnsresult
1929HttpBaseChannel::GetRequestSize(uint64_t* aRequestSize) {
1930 *aRequestSize = mRequestSize;
1931 return NS_OK;
1932}
1933
1934NS_IMETHODIMPnsresult
1935HttpBaseChannel::GetDecodedBodySize(uint64_t* aDecodedBodySize) {
1936 *aDecodedBodySize = mDecodedBodySize;
1937 return NS_OK;
1938}
1939
1940NS_IMETHODIMPnsresult
1941HttpBaseChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) {
1942 *aEncodedBodySize = mEncodedBodySize;
1943 return NS_OK;
1944}
1945
1946NS_IMETHODIMPnsresult
1947HttpBaseChannel::GetSupportsHTTP3(bool* aSupportsHTTP3) {
1948 *aSupportsHTTP3 = mSupportsHTTP3;
1949 return NS_OK;
1950}
1951
1952NS_IMETHODIMPnsresult
1953HttpBaseChannel::GetHasHTTPSRR(bool* aHasHTTPSRR) {
1954 *aHasHTTPSRR = LoadHasHTTPSRR();
1955 return NS_OK;
1956}
1957
1958NS_IMETHODIMPnsresult
1959HttpBaseChannel::GetRequestMethod(nsACString& aMethod) {
1960 mRequestHead.Method(aMethod);
1961 return NS_OK;
1962}
1963
1964NS_IMETHODIMPnsresult
1965HttpBaseChannel::SetRequestMethod(const nsACString& aMethod) {
1966 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1966); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1966, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1966); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1966
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 1966); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
1967
1968 mLoadInfo->SetIsGETRequest(aMethod.Equals("GET"));
1969
1970 const nsCString& flatMethod = PromiseFlatCStringTPromiseFlatString<char>(aMethod);
1971
1972 // Method names are restricted to valid HTTP tokens.
1973 if (!nsHttp::IsValidToken(flatMethod)) return NS_ERROR_INVALID_ARG;
1974
1975 mRequestHead.SetMethod(flatMethod);
1976 return NS_OK;
1977}
1978
1979NS_IMETHODIMPnsresult
1980HttpBaseChannel::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) {
1981 NS_ENSURE_ARG_POINTER(aReferrerInfo)do { if ((__builtin_expect(!!(!(aReferrerInfo)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReferrerInfo" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1981); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1982 *aReferrerInfo = do_AddRef(mReferrerInfo).take();
1983 return NS_OK;
1984}
1985
1986nsresult HttpBaseChannel::SetReferrerInfoInternal(
1987 nsIReferrerInfo* aReferrerInfo, bool aClone, bool aCompute,
1988 bool aRespectBeforeConnect) {
1989 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetReferrerInfoInternal [this=%p aClone(%d) "
"aCompute(%d)]\n", this, aClone, aCompute); } } while (0)
1990 ("HttpBaseChannel::SetReferrerInfoInternal [this=%p aClone(%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
, "HttpBaseChannel::SetReferrerInfoInternal [this=%p aClone(%d) "
"aCompute(%d)]\n", this, aClone, aCompute); } } while (0)
1991 "aCompute(%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
, "HttpBaseChannel::SetReferrerInfoInternal [this=%p aClone(%d) "
"aCompute(%d)]\n", this, aClone, aCompute); } } while (0)
1992 this, aClone, aCompute))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetReferrerInfoInternal [this=%p aClone(%d) "
"aCompute(%d)]\n", this, aClone, aCompute); } } while (0)
;
1993 if (aRespectBeforeConnect) {
1994 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1994); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1994, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1994); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1994
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 1994); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
1995 }
1996
1997 mReferrerInfo = aReferrerInfo;
1998
1999 // clear existing referrer, if any
2000 nsresult rv = ClearReferrerHeader();
2001 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2001)
) {
2002 return rv;
2003 }
2004
2005 if (!mReferrerInfo) {
2006 return NS_OK;
2007 }
2008
2009 if (aClone) {
2010 mReferrerInfo = static_cast<dom::ReferrerInfo*>(aReferrerInfo)->Clone();
2011 }
2012
2013 dom::ReferrerInfo* referrerInfo =
2014 static_cast<dom::ReferrerInfo*>(mReferrerInfo.get());
2015
2016 // Don't set referrerInfo if it has not been initialized.
2017 if (!referrerInfo->IsInitialized()) {
2018 mReferrerInfo = nullptr;
2019 return NS_ERROR_NOT_INITIALIZED;
2020 }
2021
2022 if (aCompute) {
2023 rv = referrerInfo->ComputeReferrer(this);
2024 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2024)
) {
2025 return rv;
2026 }
2027 }
2028
2029 nsCOMPtr<nsIURI> computedReferrer = mReferrerInfo->GetComputedReferrer();
2030 if (!computedReferrer) {
2031 return NS_OK;
2032 }
2033
2034 nsAutoCString spec;
2035 rv = computedReferrer->GetSpec(spec);
2036 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2036)
) {
2037 return rv;
2038 }
2039
2040 return SetReferrerHeader(spec, aRespectBeforeConnect);
2041}
2042
2043NS_IMETHODIMPnsresult
2044HttpBaseChannel::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
2045 return SetReferrerInfoInternal(aReferrerInfo, true, true, true);
2046}
2047
2048NS_IMETHODIMPnsresult
2049HttpBaseChannel::SetReferrerInfoWithoutClone(nsIReferrerInfo* aReferrerInfo) {
2050 return SetReferrerInfoInternal(aReferrerInfo, false, true, true);
2051}
2052
2053// Return the channel's proxy URI, or if it doesn't exist, the
2054// channel's main URI.
2055NS_IMETHODIMPnsresult
2056HttpBaseChannel::GetProxyURI(nsIURI** aOut) {
2057 NS_ENSURE_ARG_POINTER(aOut)do { if ((__builtin_expect(!!(!(aOut)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOut" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2057
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2058 nsCOMPtr<nsIURI> result(mProxyURI);
2059 result.forget(aOut);
2060 return NS_OK;
2061}
2062
2063NS_IMETHODIMPnsresult
2064HttpBaseChannel::GetRequestHeader(const nsACString& aHeader,
2065 nsACString& aValue) {
2066 aValue.Truncate();
2067
2068 // XXX might be better to search the header list directly instead of
2069 // hitting the http atom hash table.
2070 nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
2071 if (!atom) return NS_ERROR_NOT_AVAILABLE;
2072
2073 return mRequestHead.GetHeader(atom, aValue);
2074}
2075
2076NS_IMETHODIMPnsresult
2077HttpBaseChannel::SetRequestHeader(const nsACString& aHeader,
2078 const nsACString& aValue, bool aMerge) {
2079 return SetRequestHeaderInternal(aHeader, aValue, aMerge,
2080 nsHttpHeaderArray::eVarietyRequestOverride);
2081}
2082
2083nsresult HttpBaseChannel::SetRequestHeaderInternal(
2084 const nsACString& aHeader, const nsACString& aValue, bool aMerge,
2085 nsHttpHeaderArray::HeaderVariety aVariety) {
2086 const nsCString& flatHeader = PromiseFlatCStringTPromiseFlatString<char>(aHeader);
2087 const nsCString& flatValue = PromiseFlatCStringTPromiseFlatString<char>(aValue);
2088
2089 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetRequestHeader [this=%p header=\"%s\" value=\"%s\" "
"merge=%u]\n", this, flatHeader.get(), flatValue.get(), aMerge
); } } while (0)
2090 ("HttpBaseChannel::SetRequestHeader [this=%p header=\"%s\" 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
, "HttpBaseChannel::SetRequestHeader [this=%p header=\"%s\" value=\"%s\" "
"merge=%u]\n", this, flatHeader.get(), flatValue.get(), aMerge
); } } while (0)
2091 "merge=%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
, "HttpBaseChannel::SetRequestHeader [this=%p header=\"%s\" value=\"%s\" "
"merge=%u]\n", this, flatHeader.get(), flatValue.get(), aMerge
); } } while (0)
2092 this, flatHeader.get(), flatValue.get(), aMerge))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetRequestHeader [this=%p header=\"%s\" value=\"%s\" "
"merge=%u]\n", this, flatHeader.get(), flatValue.get(), aMerge
); } } while (0)
;
2093
2094 // Verify header names are valid HTTP tokens and header values are reasonably
2095 // close to whats allowed in RFC 2616.
2096 if (!nsHttp::IsValidToken(flatHeader) ||
2097 !nsHttp::IsReasonableHeaderValue(flatValue)) {
2098 return NS_ERROR_INVALID_ARG;
2099 }
2100
2101 // Mark that the User-Agent header has been modified.
2102 if (nsHttp::ResolveAtom(aHeader) == nsHttp::User_Agent) {
2103 StoreIsUserAgentHeaderModified(true);
2104 }
2105
2106 return mRequestHead.SetHeader(aHeader, flatValue, aMerge, aVariety);
2107}
2108
2109NS_IMETHODIMPnsresult
2110HttpBaseChannel::SetNewReferrerInfo(const nsACString& aUrl,
2111 nsIReferrerInfo::ReferrerPolicyIDL aPolicy,
2112 bool aSendReferrer) {
2113 nsresult rv;
2114 // Create URI from string
2115 nsCOMPtr<nsIURI> aURI;
2116 rv = NS_NewURI(getter_AddRefs(aURI), aUrl);
2117 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2117); return rv; } } while (false)
;
2118 // Create new ReferrerInfo and initialize it.
2119 nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo();
2120 rv = referrerInfo->Init(aPolicy, aSendReferrer, aURI);
2121 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2121); return rv; } } while (false)
;
2122 // Set ReferrerInfo
2123 return SetReferrerInfo(referrerInfo);
2124}
2125
2126NS_IMETHODIMPnsresult
2127HttpBaseChannel::SetEmptyRequestHeader(const nsACString& aHeader) {
2128 const nsCString& flatHeader = PromiseFlatCStringTPromiseFlatString<char>(aHeader);
2129
2130 LOG(("HttpBaseChannel::SetEmptyRequestHeader [this=%p header=\"%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
, "HttpBaseChannel::SetEmptyRequestHeader [this=%p header=\"%s\"]\n"
, this, flatHeader.get()); } } while (0)
2131 flatHeader.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetEmptyRequestHeader [this=%p header=\"%s\"]\n"
, this, flatHeader.get()); } } while (0)
;
2132
2133 // Verify header names are valid HTTP tokens and header values are reasonably
2134 // close to whats allowed in RFC 2616.
2135 if (!nsHttp::IsValidToken(flatHeader)) {
2136 return NS_ERROR_INVALID_ARG;
2137 }
2138
2139 // Mark that the User-Agent header has been modified.
2140 if (nsHttp::ResolveAtom(aHeader) == nsHttp::User_Agent) {
2141 StoreIsUserAgentHeaderModified(true);
2142 }
2143
2144 return mRequestHead.SetEmptyHeader(aHeader);
2145}
2146
2147NS_IMETHODIMPnsresult
2148HttpBaseChannel::VisitRequestHeaders(nsIHttpHeaderVisitor* visitor) {
2149 return mRequestHead.VisitHeaders(visitor);
2150}
2151
2152NS_IMETHODIMPnsresult
2153HttpBaseChannel::VisitNonDefaultRequestHeaders(nsIHttpHeaderVisitor* visitor) {
2154 return mRequestHead.VisitHeaders(visitor,
2155 nsHttpHeaderArray::eFilterSkipDefault);
2156}
2157
2158NS_IMETHODIMPnsresult
2159HttpBaseChannel::GetResponseHeader(const nsACString& header,
2160 nsACString& value) {
2161 value.Truncate();
2162
2163 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2164
2165 nsHttpAtom atom = nsHttp::ResolveAtom(header);
2166 if (!atom) return NS_ERROR_NOT_AVAILABLE;
2167
2168 return mResponseHead->GetHeader(atom, value);
2169}
2170
2171NS_IMETHODIMPnsresult
2172HttpBaseChannel::SetResponseHeader(const nsACString& header,
2173 const nsACString& value, bool merge) {
2174 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetResponseHeader [this=%p header=\"%s\" value=\"%s\" "
"merge=%u]\n", this, TPromiseFlatString<char>(header).
get(), TPromiseFlatString<char>(value).get(), merge); }
} while (0)
2175 ("HttpBaseChannel::SetResponseHeader [this=%p header=\"%s\" 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
, "HttpBaseChannel::SetResponseHeader [this=%p header=\"%s\" value=\"%s\" "
"merge=%u]\n", this, TPromiseFlatString<char>(header).
get(), TPromiseFlatString<char>(value).get(), merge); }
} while (0)
2176 "merge=%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
, "HttpBaseChannel::SetResponseHeader [this=%p header=\"%s\" value=\"%s\" "
"merge=%u]\n", this, TPromiseFlatString<char>(header).
get(), TPromiseFlatString<char>(value).get(), merge); }
} while (0)
2177 this, PromiseFlatCString(header).get(), PromiseFlatCString(value).get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetResponseHeader [this=%p header=\"%s\" value=\"%s\" "
"merge=%u]\n", this, TPromiseFlatString<char>(header).
get(), TPromiseFlatString<char>(value).get(), merge); }
} while (0)
2178 merge))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetResponseHeader [this=%p header=\"%s\" value=\"%s\" "
"merge=%u]\n", this, TPromiseFlatString<char>(header).
get(), TPromiseFlatString<char>(value).get(), merge); }
} while (0)
;
2179
2180 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2181
2182 nsHttpAtom atom = nsHttp::ResolveAtom(header);
2183 if (!atom) return NS_ERROR_NOT_AVAILABLE;
2184
2185 // these response headers must not be changed
2186 if (atom == nsHttp::Content_Type || atom == nsHttp::Content_Length ||
2187 atom == nsHttp::Content_Encoding || atom == nsHttp::Trailer ||
2188 atom == nsHttp::Transfer_Encoding) {
2189 return NS_ERROR_ILLEGAL_VALUE;
2190 }
2191
2192 StoreResponseHeadersModified(true);
2193
2194 return mResponseHead->SetHeader(header, value, merge);
2195}
2196
2197NS_IMETHODIMPnsresult
2198HttpBaseChannel::VisitResponseHeaders(nsIHttpHeaderVisitor* visitor) {
2199 if (!mResponseHead) {
2200 return NS_ERROR_NOT_AVAILABLE;
2201 }
2202 return mResponseHead->VisitHeaders(visitor,
2203 nsHttpHeaderArray::eFilterResponse);
2204}
2205
2206NS_IMETHODIMPnsresult
2207HttpBaseChannel::GetOriginalResponseHeader(const nsACString& aHeader,
2208 nsIHttpHeaderVisitor* aVisitor) {
2209 if (!mResponseHead) {
2210 return NS_ERROR_NOT_AVAILABLE;
2211 }
2212
2213 nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
2214 if (!atom) {
2215 return NS_ERROR_NOT_AVAILABLE;
2216 }
2217
2218 return mResponseHead->GetOriginalHeader(atom, aVisitor);
2219}
2220
2221NS_IMETHODIMPnsresult
2222HttpBaseChannel::VisitOriginalResponseHeaders(nsIHttpHeaderVisitor* aVisitor) {
2223 if (!mResponseHead) {
2224 return NS_ERROR_NOT_AVAILABLE;
2225 }
2226
2227 return mResponseHead->VisitHeaders(
2228 aVisitor, nsHttpHeaderArray::eFilterResponseOriginal);
2229}
2230
2231NS_IMETHODIMPnsresult
2232HttpBaseChannel::GetAllowSTS(bool* value) {
2233 NS_ENSURE_ARG_POINTER(value)do { if ((__builtin_expect(!!(!(value)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "value" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2233
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2234 *value = LoadAllowSTS();
2235 return NS_OK;
2236}
2237
2238NS_IMETHODIMPnsresult
2239HttpBaseChannel::SetAllowSTS(bool value) {
2240 // This controls whether the parent process honors HSTS for this channel, so
2241 // it must not be settable from a content process.
2242 if (!XRE_IsParentProcess()) {
2243 MOZ_ASSERT(value == true, "allowSTS = false is parent process only")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(value == true)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(value == true))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("value == true" " ("
"allowSTS = false is parent process only" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2243); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value == true"
") (" "allowSTS = false is parent process only" ")"); do { MOZ_CrashSequence
(__null, 2243); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2244 return NS_OK;
2245 }
2246 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2246); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2246, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2246); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2246
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 2246); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
2247 StoreAllowSTS(value);
2248 return NS_OK;
2249}
2250
2251NS_IMETHODIMPnsresult
2252HttpBaseChannel::GetIsOCSP(bool* value) {
2253 NS_ENSURE_ARG_POINTER(value)do { if ((__builtin_expect(!!(!(value)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "value" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2253
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2254 *value = LoadIsOCSP();
2255 return NS_OK;
2256}
2257
2258NS_IMETHODIMPnsresult
2259HttpBaseChannel::SetIsOCSP(bool value) {
2260 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2260); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2260, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2260); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2260
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 2260); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
2261 StoreIsOCSP(value);
2262 return NS_OK;
2263}
2264
2265NS_IMETHODIMPnsresult
2266HttpBaseChannel::GetIsUserAgentHeaderModified(bool* value) {
2267 NS_ENSURE_ARG_POINTER(value)do { if ((__builtin_expect(!!(!(value)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "value" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2267
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2268 *value = LoadIsUserAgentHeaderModified();
2269 return NS_OK;
2270}
2271
2272NS_IMETHODIMPnsresult
2273HttpBaseChannel::SetIsUserAgentHeaderModified(bool value) {
2274 StoreIsUserAgentHeaderModified(value);
2275 return NS_OK;
2276}
2277
2278NS_IMETHODIMPnsresult
2279HttpBaseChannel::GetRedirectionLimit(uint32_t* value) {
2280 NS_ENSURE_ARG_POINTER(value)do { if ((__builtin_expect(!!(!(value)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "value" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2280
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2281 *value = mRedirectionLimit;
2282 return NS_OK;
2283}
2284
2285NS_IMETHODIMPnsresult
2286HttpBaseChannel::SetRedirectionLimit(uint32_t value) {
2287 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2287); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2287, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2287); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2287
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 2287); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
2288
2289 mRedirectionLimit = std::min<uint32_t>(value, 0xff);
2290 return NS_OK;
2291}
2292
2293nsresult HttpBaseChannel::OverrideSecurityInfo(
2294 nsITransportSecurityInfo* aSecurityInfo) {
2295 MOZ_ASSERT(!mSecurityInfo,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mSecurityInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mSecurityInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mSecurityInfo"
" (" "This can only be called when we don't have a security info "
"object already" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mSecurityInfo"
") (" "This can only be called when we don't have a security info "
"object already" ")"); do { MOZ_CrashSequence(__null, 2297);
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2296 "This can only be called when we don't have a security info "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mSecurityInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mSecurityInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mSecurityInfo"
" (" "This can only be called when we don't have a security info "
"object already" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mSecurityInfo"
") (" "This can only be called when we don't have a security info "
"object already" ")"); do { MOZ_CrashSequence(__null, 2297);
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2297 "object already")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mSecurityInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mSecurityInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mSecurityInfo"
" (" "This can only be called when we don't have a security info "
"object already" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mSecurityInfo"
") (" "This can only be called when we don't have a security info "
"object already" ")"); do { MOZ_CrashSequence(__null, 2297);
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
2298 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSecurityInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSecurityInfo))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSecurityInfo" " ("
"This can only be called with a valid security info object" ")"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2300
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aSecurityInfo"
") (" "This can only be called with a valid security info object"
")"); do { MOZ_CrashSequence(__null, 2300); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2299 aSecurityInfo,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSecurityInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSecurityInfo))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSecurityInfo" " ("
"This can only be called with a valid security info object" ")"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2300
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aSecurityInfo"
") (" "This can only be called with a valid security info object"
")"); do { MOZ_CrashSequence(__null, 2300); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2300 "This can only be called with a valid security info object")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSecurityInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSecurityInfo))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSecurityInfo" " ("
"This can only be called with a valid security info object" ")"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2300
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aSecurityInfo"
") (" "This can only be called with a valid security info object"
")"); do { MOZ_CrashSequence(__null, 2300); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2301 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()"
" (" "This can only be called on channels that are not bypassing "
"interception" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
") (" "This can only be called on channels that are not bypassing "
"interception" ")"); do { MOZ_CrashSequence(__null, 2303); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2302 "This can only be called on channels that are not bypassing "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!BypassServiceWorker())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!BypassServiceWorker()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!BypassServiceWorker()"
" (" "This can only be called on channels that are not bypassing "
"interception" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
") (" "This can only be called on channels that are not bypassing "
"interception" ")"); do { MOZ_CrashSequence(__null, 2303); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2303 "interception")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!BypassServiceWorker())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!BypassServiceWorker()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!BypassServiceWorker()"
" (" "This can only be called on channels that are not bypassing "
"interception" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
") (" "This can only be called on channels that are not bypassing "
"interception" ")"); do { MOZ_CrashSequence(__null, 2303); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
2304 MOZ_ASSERT(LoadResponseCouldBeSynthesized(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadResponseCouldBeSynthesized())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadResponseCouldBeSynthesized
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("LoadResponseCouldBeSynthesized()" " (" "This can only be called on channels that can be intercepted"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadResponseCouldBeSynthesized()"
") (" "This can only be called on channels that can be intercepted"
")"); do { MOZ_CrashSequence(__null, 2305); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2305 "This can only be called on channels that can be intercepted")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadResponseCouldBeSynthesized())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadResponseCouldBeSynthesized
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("LoadResponseCouldBeSynthesized()" " (" "This can only be called on channels that can be intercepted"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadResponseCouldBeSynthesized()"
") (" "This can only be called on channels that can be intercepted"
")"); do { MOZ_CrashSequence(__null, 2305); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2306 if (mSecurityInfo) {
2307 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::OverrideSecurityInfo mSecurityInfo is null! "
"[this=%p]\n", this); } } while (0)
2308 ("HttpBaseChannel::OverrideSecurityInfo mSecurityInfo is null! "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::OverrideSecurityInfo mSecurityInfo is null! "
"[this=%p]\n", this); } } while (0)
2309 "[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
, "HttpBaseChannel::OverrideSecurityInfo mSecurityInfo is null! "
"[this=%p]\n", this); } } while (0)
2310 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::OverrideSecurityInfo mSecurityInfo is null! "
"[this=%p]\n", this); } } while (0)
;
2311 return NS_ERROR_UNEXPECTED;
2312 }
2313 if (!LoadResponseCouldBeSynthesized()) {
2314 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::OverrideSecurityInfo channel cannot be intercepted! "
"[this=%p]\n", this); } } while (0)
2315 ("HttpBaseChannel::OverrideSecurityInfo channel cannot be intercepted! "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::OverrideSecurityInfo channel cannot be intercepted! "
"[this=%p]\n", this); } } while (0)
2316 "[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
, "HttpBaseChannel::OverrideSecurityInfo channel cannot be intercepted! "
"[this=%p]\n", this); } } while (0)
2317 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::OverrideSecurityInfo channel cannot be intercepted! "
"[this=%p]\n", this); } } while (0)
;
2318 return NS_ERROR_UNEXPECTED;
2319 }
2320
2321 mSecurityInfo = aSecurityInfo;
2322 return NS_OK;
2323}
2324
2325NS_IMETHODIMPnsresult
2326HttpBaseChannel::IsNoStoreResponse(bool* value) {
2327 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2328 *value = mResponseHead->NoStore();
2329 return NS_OK;
2330}
2331
2332NS_IMETHODIMPnsresult
2333HttpBaseChannel::IsNoCacheResponse(bool* value) {
2334 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2335 *value = mResponseHead->NoCache();
2336 if (!*value) *value = mResponseHead->ExpiresInPast();
2337 return NS_OK;
2338}
2339
2340NS_IMETHODIMPnsresult
2341HttpBaseChannel::GetResponseStatus(uint32_t* aValue) {
2342 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2343 *aValue = mResponseHead->Status();
2344 return NS_OK;
2345}
2346
2347NS_IMETHODIMPnsresult
2348HttpBaseChannel::GetResponseStatusText(nsACString& aValue) {
2349 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2350 nsAutoCString version;
2351 // https://fetch.spec.whatwg.org :
2352 // Responses over an HTTP/2 connection will always have the empty byte
2353 // sequence as status message as HTTP/2 does not support them.
2354 if (NS_WARN_IF(NS_FAILED(GetProtocolVersion(version)))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(GetProtocolVersion
(version))), 0))), "NS_FAILED(GetProtocolVersion(version))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2354)
||
2355 !version.EqualsLiteral("h2")) {
2356 mResponseHead->StatusText(aValue);
2357 }
2358 return NS_OK;
2359}
2360
2361NS_IMETHODIMPnsresult
2362HttpBaseChannel::GetRequestSucceeded(bool* aValue) {
2363 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2364 uint32_t status = mResponseHead->Status();
2365 *aValue = (status / 100 == 2);
2366 return NS_OK;
2367}
2368
2369NS_IMETHODIMPnsresult
2370HttpBaseChannel::RedirectTo(nsIURI* targetURI) {
2371 NS_ENSURE_ARG(targetURI)do { if ((__builtin_expect(!!(!(targetURI)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "targetURI" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2371
); return NS_ERROR_INVALID_ARG; } } while (false)
;
2372
2373 nsAutoCString spec;
2374 targetURI->GetAsciiSpec(spec);
2375 LOG(("HttpBaseChannel::RedirectTo [this=%p, uri=%s]", this, spec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::RedirectTo [this=%p, uri=%s]", this, spec
.get()); } } while (0)
;
2376 LogCallingScriptLocation(this);
2377
2378 // We cannot redirect after OnStartRequest of the listener
2379 // has been called, since to redirect we have to switch channels
2380 // and the dance with OnStartRequest et al has to start over.
2381 // This would break the nsIStreamListener contract.
2382 NS_ENSURE_FALSE(LoadOnStartRequestCalled(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(!(LoadOnStartRequestCalled())
)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!(LoadOnStartRequestCalled())"
") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2382); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
2383
2384 // The first parameter is the URI we would like to redirect to
2385 // The second parameter should default to false if normal redirect
2386 mAPIRedirectTo =
2387 Some(mozilla::MakeCompactPair(nsCOMPtr<nsIURI>(targetURI), false));
2388
2389 // Only Web Extensions are allowed to redirect a channel to a data:
2390 // URI. To avoid any bypasses after the channel was flagged by
2391 // the WebRequst API, we are dropping the flag here.
2392 mLoadInfo->SetAllowInsecureRedirectToDataURI(false);
2393
2394 // We may want to rewrite origin allowance, hence we need an
2395 // artificial response head.
2396 if (!mResponseHead) {
2397 mResponseHead.reset(new nsHttpResponseHead());
2398 }
2399 return NS_OK;
2400}
2401
2402NS_IMETHODIMPnsresult
2403HttpBaseChannel::TransparentRedirectTo(nsIURI* targetURI) {
2404 LOG(("HttpBaseChannel::TransparentRedirectTo [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
, "HttpBaseChannel::TransparentRedirectTo [this=%p]", this); }
} while (0)
;
2405 RedirectTo(targetURI);
2406 MOZ_ASSERT(mAPIRedirectTo, "How did this happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAPIRedirectTo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAPIRedirectTo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mAPIRedirectTo"
" (" "How did this happen?" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2406); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo"
") (" "How did this happen?" ")"); do { MOZ_CrashSequence(__null
, 2406); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
2407 mAPIRedirectTo->second() = true;
2408 return NS_OK;
2409}
2410
2411NS_IMETHODIMPnsresult
2412HttpBaseChannel::UpgradeToSecure() {
2413 // Upgrades are handled internally between http-on-modify-request and
2414 // http-on-before-connect, which means upgrades are only possible during
2415 // on-modify, or WebRequest.onBeforeRequest in Web Extensions. Once we are
2416 // past the code path where upgrades are handled, attempting an upgrade
2417 // will throw an error.
2418 NS_ENSURE_TRUE(LoadUpgradableToSecure(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(LoadUpgradableToSecure())), 0
))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "LoadUpgradableToSecure()"
") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2418); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
2419
2420 StoreUpgradeToSecure(true);
2421 // todo: Currently UpgradeToSecure() is called only by web extensions, if
2422 // that ever changes, we need to update the following telemetry collection
2423 // to reflect any future changes.
2424 mLoadInfo->SetHttpsUpgradeTelemetry(nsILoadInfo::WEB_EXTENSION_UPGRADE);
2425
2426 return NS_OK;
2427}
2428
2429NS_IMETHODIMPnsresult
2430HttpBaseChannel::GetRequestObserversCalled(bool* aCalled) {
2431 NS_ENSURE_ARG_POINTER(aCalled)do { if ((__builtin_expect(!!(!(aCalled)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCalled" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2431
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2432 *aCalled = LoadRequestObserversCalled();
2433 return NS_OK;
2434}
2435
2436NS_IMETHODIMPnsresult
2437HttpBaseChannel::SetRequestObserversCalled(bool aCalled) {
2438 StoreRequestObserversCalled(aCalled);
2439 return NS_OK;
2440}
2441
2442NS_IMETHODIMPnsresult
2443HttpBaseChannel::GetRequestContextID(uint64_t* aRCID) {
2444 NS_ENSURE_ARG_POINTER(aRCID)do { if ((__builtin_expect(!!(!(aRCID)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRCID" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2444
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2445 *aRCID = mRequestContextID;
2446 return NS_OK;
2447}
2448
2449NS_IMETHODIMPnsresult
2450HttpBaseChannel::SetRequestContextID(uint64_t aRCID) {
2451 mRequestContextID = aRCID;
2452 return NS_OK;
2453}
2454
2455NS_IMETHODIMPnsresult
2456HttpBaseChannel::GetIsMainDocumentChannel(bool* aValue) {
2457 NS_ENSURE_ARG_POINTER(aValue)do { if ((__builtin_expect(!!(!(aValue)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aValue" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2457
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2458 *aValue = IsNavigation();
2459 return NS_OK;
2460}
2461
2462NS_IMETHODIMPnsresult
2463HttpBaseChannel::SetIsMainDocumentChannel(bool aValue) {
2464 StoreForceMainDocumentChannel(aValue);
2465 return NS_OK;
2466}
2467
2468NS_IMETHODIMPnsresult
2469HttpBaseChannel::GetIsUserAgentHeaderOutdated(bool* aValue) {
2470 NS_ENSURE_ARG_POINTER(aValue)do { if ((__builtin_expect(!!(!(aValue)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aValue" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2470
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2471 *aValue = LoadIsUserAgentHeaderOutdated();
2472 return NS_OK;
2473}
2474
2475NS_IMETHODIMPnsresult
2476HttpBaseChannel::SetIsUserAgentHeaderOutdated(bool aValue) {
2477 StoreIsUserAgentHeaderOutdated(aValue);
2478 return NS_OK;
2479}
2480
2481NS_IMETHODIMPnsresult
2482HttpBaseChannel::GetProtocolVersion(nsACString& aProtocolVersion) {
2483 // Try to use ALPN if available and if it is not for a proxy, i.e if an
2484 // https proxy was not used or if https proxy was used but the connection to
2485 // the origin server is also https. In the case, an https proxy was used and
2486 // the connection to the origin server was http, mSecurityInfo will be from
2487 // the proxy.
2488 if (!mConnectionInfo || !mConnectionInfo->UsingHttpsProxy() ||
2489 mConnectionInfo->EndToEndSSL()) {
2490 nsAutoCString protocol;
2491 if (mSecurityInfo &&
2492 NS_SUCCEEDED(mSecurityInfo->GetNegotiatedNPN(protocol))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mSecurityInfo->
GetNegotiatedNPN(protocol))), 1)))
&&
2493 !protocol.IsEmpty()) {
2494 // The negotiated protocol was not empty so we can use it.
2495 aProtocolVersion = std::move(protocol);
2496 return NS_OK;
2497 }
2498 }
2499
2500 if (mResponseHead) {
2501 HttpVersion version = mResponseHead->Version();
2502 aProtocolVersion.Assign(nsHttp::GetProtocolVersion(version));
2503 return NS_OK;
2504 }
2505
2506 return NS_ERROR_NOT_AVAILABLE;
2507}
2508
2509//-----------------------------------------------------------------------------
2510// HttpBaseChannel::nsIHttpChannelInternal
2511//-----------------------------------------------------------------------------
2512
2513NS_IMETHODIMPnsresult
2514HttpBaseChannel::SetTopWindowURIIfUnknown(nsIURI* aTopWindowURI) {
2515 if (!aTopWindowURI) {
2516 return NS_ERROR_INVALID_ARG;
2517 }
2518
2519 if (mTopWindowURI) {
2520 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] " "mTopWindowURI is already set.\n"
, this); } } while (0)
2521 ("HttpChannelBase::SetTopWindowURIIfUnknown [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
, "HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] " "mTopWindowURI is already set.\n"
, this); } } while (0)
2522 "mTopWindowURI is already set.\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] " "mTopWindowURI is already set.\n"
, this); } } while (0)
2523 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] " "mTopWindowURI is already set.\n"
, this); } } while (0)
;
2524 return NS_ERROR_FAILURE;
2525 }
2526
2527 nsCOMPtr<nsIURI> topWindowURI;
2528 (void)GetTopWindowURI(getter_AddRefs(topWindowURI));
2529
2530 // Don't modify |mTopWindowURI| if we can get one from GetTopWindowURI().
2531 if (topWindowURI) {
2532 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] " "Return an error since we got a top window uri.\n"
, this); } } while (0)
2533 ("HttpChannelBase::SetTopWindowURIIfUnknown [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
, "HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] " "Return an error since we got a top window uri.\n"
, this); } } while (0)
2534 "Return an error since we got a top window uri.\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] " "Return an error since we got a top window uri.\n"
, this); } } while (0)
2535 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] " "Return an error since we got a top window uri.\n"
, this); } } while (0)
;
2536 return NS_ERROR_FAILURE;
2537 }
2538
2539 mTopWindowURI = aTopWindowURI;
2540 return NS_OK;
2541}
2542
2543NS_IMETHODIMPnsresult
2544HttpBaseChannel::GetTopWindowURI(nsIURI** aTopWindowURI) {
2545 nsCOMPtr<nsIURI> uriBeingLoaded =
2546 AntiTrackingUtils::MaybeGetDocumentURIBeingLoaded(this);
2547 return GetTopWindowURI(uriBeingLoaded, aTopWindowURI);
2548}
2549
2550nsresult HttpBaseChannel::GetTopWindowURI(nsIURI* aURIBeingLoaded,
2551 nsIURI** aTopWindowURI) {
2552 nsresult rv = NS_OK;
2553 nsCOMPtr<mozIThirdPartyUtil> util;
2554 // Only compute the top window URI once. In e10s, this must be computed in the
2555 // child. The parent gets the top window URI through HttpChannelOpenArgs.
2556 if (!mTopWindowURI) {
2557 util = components::ThirdPartyUtil::Service();
2558 if (!util) {
2559 return NS_ERROR_NOT_AVAILABLE;
2560 }
2561 nsCOMPtr<mozIDOMWindowProxy> win;
2562 rv = util->GetTopWindowForChannel(this, aURIBeingLoaded,
2563 getter_AddRefs(win));
2564 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2565 rv = util->GetURIFromWindow(win, getter_AddRefs(mTopWindowURI));
2566#if DEBUG1
2567 if (mTopWindowURI) {
2568 nsCString spec;
2569 if (NS_SUCCEEDED(mTopWindowURI->GetSpec(spec))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mTopWindowURI->
GetSpec(spec))), 1)))
) {
2570 LOG(("HttpChannelBase::Setting topwindow URI spec %s [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
, "HttpChannelBase::Setting topwindow URI spec %s [this=%p]\n"
, spec.get(), this); } } while (0)
2571 spec.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
, "HttpChannelBase::Setting topwindow URI spec %s [this=%p]\n"
, spec.get(), this); } } while (0)
;
2572 }
2573 }
2574#endif
2575 }
2576 }
2577 *aTopWindowURI = do_AddRef(mTopWindowURI).take();
2578 return rv;
2579}
2580
2581NS_IMETHODIMPnsresult
2582HttpBaseChannel::GetDocumentURI(nsIURI** aDocumentURI) {
2583 NS_ENSURE_ARG_POINTER(aDocumentURI)do { if ((__builtin_expect(!!(!(aDocumentURI)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocumentURI" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2583); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2584 *aDocumentURI = do_AddRef(mDocumentURI).take();
2585 return NS_OK;
2586}
2587
2588NS_IMETHODIMPnsresult
2589HttpBaseChannel::SetDocumentURI(nsIURI* aDocumentURI) {
2590 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2590); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2590, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2590); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2590
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 2590); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
2591 mDocumentURI = aDocumentURI;
2592 return NS_OK;
2593}
2594
2595NS_IMETHODIMPnsresult
2596HttpBaseChannel::GetRequestVersion(uint32_t* major, uint32_t* minor) {
2597 HttpVersion version = mRequestHead.Version();
2598
2599 if (major) {
2600 *major = static_cast<uint32_t>(version) / 10;
2601 }
2602 if (minor) {
2603 *minor = static_cast<uint32_t>(version) % 10;
2604 }
2605
2606 return NS_OK;
2607}
2608
2609NS_IMETHODIMPnsresult
2610HttpBaseChannel::GetResponseVersion(uint32_t* major, uint32_t* minor) {
2611 if (!mResponseHead) {
2612 *major = *minor = 0; // we should at least be kind about it
2613 return NS_ERROR_NOT_AVAILABLE;
2614 }
2615
2616 HttpVersion version = mResponseHead->Version();
2617
2618 if (major) {
2619 *major = static_cast<uint32_t>(version) / 10;
2620 }
2621 if (minor) {
2622 *minor = static_cast<uint32_t>(version) % 10;
2623 }
2624
2625 return NS_OK;
2626}
2627
2628bool HttpBaseChannel::IsBrowsingContextDiscarded() const {
2629 // If there is no loadGroup attached to the current channel, we check the
2630 // global private browsing state for the private channel instead. For
2631 // non-private channel, we will always return false here.
2632 //
2633 // Note that we can only access the global private browsing state in the
2634 // parent process. So, we will fallback to just return false in the content
2635 // process.
2636 if (!mLoadGroup) {
2637 if (!XRE_IsParentProcess()) {
2638 return false;
2639 }
2640
2641 return mLoadInfo->GetOriginAttributes().IsPrivateBrowsing() &&
2642 !dom::CanonicalBrowsingContext::IsPrivateBrowsingActive();
2643 }
2644
2645 return mLoadGroup->GetIsBrowsingContextDiscarded();
2646}
2647
2648// https://mikewest.github.io/corpp/#process-navigation-response
2649nsresult HttpBaseChannel::ProcessCrossOriginEmbedderPolicyHeader() {
2650 nsresult rv;
2651 if (!StaticPrefs::browser_tabs_remote_useCrossOriginEmbedderPolicy()) {
2652 return NS_OK;
2653 }
2654
2655 // Only consider Cross-Origin-Embedder-Policy for document loads.
2656 if (mLoadInfo->GetExternalContentPolicyType() !=
2657 ExtContentPolicy::TYPE_DOCUMENT &&
2658 mLoadInfo->GetExternalContentPolicyType() !=
2659 ExtContentPolicy::TYPE_SUBDOCUMENT) {
2660 return NS_OK;
2661 }
2662
2663 nsILoadInfo::CrossOriginEmbedderPolicy resultPolicy =
2664 nsILoadInfo::EMBEDDER_POLICY_NULL;
2665 bool isCoepCredentiallessEnabled;
2666 rv = mLoadInfo->GetIsOriginTrialCoepCredentiallessEnabledForTopLevel(
2667 &isCoepCredentiallessEnabled);
2668 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2668); return rv; } } while (false)
;
2669 rv = GetResponseEmbedderPolicy(isCoepCredentiallessEnabled, &resultPolicy);
2670 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2671 return NS_OK;
2672 }
2673
2674 // https://html.spec.whatwg.org/multipage/origin.html#coep
2675 if (mLoadInfo->GetExternalContentPolicyType() ==
2676 ExtContentPolicy::TYPE_SUBDOCUMENT &&
2677 !nsHttpChannel::IsRedirectStatus(mResponseHead->Status()) &&
2678 mLoadInfo->GetLoadingEmbedderPolicy() !=
2679 nsILoadInfo::EMBEDDER_POLICY_NULL &&
2680 resultPolicy != nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP &&
2681 resultPolicy != nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS) {
2682 return NS_ERROR_DOM_COEP_FAILED;
2683 }
2684
2685 return NS_OK;
2686}
2687
2688// https://mikewest.github.io/corpp/#corp-check
2689nsresult HttpBaseChannel::ProcessCrossOriginResourcePolicyHeader() {
2690 // Fetch 4.5.9
2691 dom::RequestMode requestMode;
2692 MOZ_ALWAYS_SUCCEEDS(GetRequestMode(&requestMode))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(GetRequestMode(&requestMode))), 1)))), 1))) { } else { do
{ do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(GetRequestMode(&requestMode))"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2692
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(GetRequestMode(&requestMode))"
")"); do { MOZ_CrashSequence(__null, 2692); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2693 // XXX this seems wrong per spec? What about navigate
2694 if (requestMode != RequestMode::No_cors) {
2695 return NS_OK;
2696 }
2697
2698 // We only apply this for resources.
2699 auto extContentPolicyType = mLoadInfo->GetExternalContentPolicyType();
2700 if (extContentPolicyType == ExtContentPolicy::TYPE_DOCUMENT ||
2701 extContentPolicyType == ExtContentPolicy::TYPE_WEBSOCKET ||
2702 extContentPolicyType == ExtContentPolicy::TYPE_SAVEAS_DOWNLOAD) {
2703 return NS_OK;
2704 }
2705
2706 if (extContentPolicyType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
2707 // COEP pref off, skip CORP checking for subdocument.
2708 if (!StaticPrefs::browser_tabs_remote_useCrossOriginEmbedderPolicy()) {
2709 return NS_OK;
2710 }
2711 // COEP 3.2.1.2 when request targets a nested browsing context then embedder
2712 // policy value is "unsafe-none", then return allowed.
2713 if (mLoadInfo->GetLoadingEmbedderPolicy() ==
2714 nsILoadInfo::EMBEDDER_POLICY_NULL) {
2715 return NS_OK;
2716 }
2717 }
2718
2719 MOZ_ASSERT(mLoadInfo->GetLoadingPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetLoadingPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo->GetLoadingPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLoadInfo->GetLoadingPrincipal()" " (" "Resources should always have a LoadingPrincipal"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2720); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetLoadingPrincipal()"
") (" "Resources should always have a LoadingPrincipal" ")")
; do { MOZ_CrashSequence(__null, 2720); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2720 "Resources should always have a LoadingPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetLoadingPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo->GetLoadingPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLoadInfo->GetLoadingPrincipal()" " (" "Resources should always have a LoadingPrincipal"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2720); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetLoadingPrincipal()"
") (" "Resources should always have a LoadingPrincipal" ")")
; do { MOZ_CrashSequence(__null, 2720); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2721 if (!mResponseHead) {
2722 return NS_OK;
2723 }
2724
2725 if (mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal()) {
2726 return NS_OK;
2727 }
2728
2729 nsAutoCString content;
2730 (void)mResponseHead->GetHeader(nsHttp::Cross_Origin_Resource_Policy, content);
2731
2732 if (StaticPrefs::browser_tabs_remote_useCrossOriginEmbedderPolicy()) {
2733 if (content.IsEmpty()) {
2734 if (mLoadInfo->GetLoadingEmbedderPolicy() ==
2735 nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS) {
2736 bool requestIncludesCredentials = false;
2737 nsresult rv = GetCorsIncludeCredentials(&requestIncludesCredentials);
2738 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2739 return NS_OK;
2740 }
2741 // COEP: Set policy to `same-origin` if: response’s
2742 // request-includes-credentials is true, or forNavigation is true.
2743 if (requestIncludesCredentials ||
2744 extContentPolicyType == ExtContentPolicyType::TYPE_SUBDOCUMENT) {
2745 content = "same-origin"_ns;
2746 }
2747 } else if (mLoadInfo->GetLoadingEmbedderPolicy() ==
2748 nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP) {
2749 // COEP 3.2.1.6 If policy is null, and embedder policy is
2750 // "require-corp", set policy to "same-origin". Note that we treat
2751 // invalid value as "cross-origin", which spec indicates. We might want
2752 // to make that stricter.
2753 content = "same-origin"_ns;
2754 }
2755 }
2756 }
2757
2758 if (content.IsEmpty()) {
2759 return NS_OK;
2760 }
2761
2762 nsCOMPtr<nsIPrincipal> channelOrigin;
2763 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
2764 this, getter_AddRefs(channelOrigin));
2765
2766 // Cross-Origin-Resource-Policy = %s"same-origin" / %s"same-site" /
2767 // %s"cross-origin"
2768 if (content.EqualsLiteral("same-origin")) {
2769 if (!channelOrigin->Equals(mLoadInfo->GetLoadingPrincipal())) {
2770 return NS_ERROR_DOM_CORP_FAILED;
2771 }
2772 return NS_OK;
2773 }
2774 if (content.EqualsLiteral("same-site")) {
2775 nsAutoCString documentBaseDomain;
2776 nsAutoCString resourceBaseDomain;
2777 mLoadInfo->GetLoadingPrincipal()->GetBaseDomain(documentBaseDomain);
2778 channelOrigin->GetBaseDomain(resourceBaseDomain);
2779 if (documentBaseDomain != resourceBaseDomain) {
2780 return NS_ERROR_DOM_CORP_FAILED;
2781 }
2782
2783 nsCOMPtr<nsIURI> resourceURI = channelOrigin->GetURI();
2784 if (!mLoadInfo->GetLoadingPrincipal()->SchemeIs("https") &&
2785 resourceURI->SchemeIs("https")) {
2786 return NS_ERROR_DOM_CORP_FAILED;
2787 }
2788
2789 return NS_OK;
2790 }
2791
2792 return NS_OK;
2793}
2794
2795// See https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
2796// This method runs steps 1-4 of the algorithm to compare
2797// cross-origin-opener policies
2798static bool CompareCrossOriginOpenerPolicies(
2799 nsILoadInfo::CrossOriginOpenerPolicy documentPolicy,
2800 nsIPrincipal* documentOrigin,
2801 nsILoadInfo::CrossOriginOpenerPolicy resultPolicy,
2802 nsIPrincipal* resultOrigin) {
2803 if (documentPolicy == nsILoadInfo::OPENER_POLICY_UNSAFE_NONE &&
2804 resultPolicy == nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) {
2805 return true;
2806 }
2807
2808 if (documentPolicy == nsILoadInfo::OPENER_POLICY_UNSAFE_NONE ||
2809 resultPolicy == nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) {
2810 return false;
2811 }
2812
2813 if (documentPolicy == resultPolicy && documentOrigin->Equals(resultOrigin)) {
2814 return true;
2815 }
2816
2817 return false;
2818}
2819
2820// This runs steps 1-5 of the algorithm when navigating a top level document.
2821// See https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
2822nsresult HttpBaseChannel::ComputeCrossOriginOpenerPolicyMismatch() {
2823 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 2823
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 2823); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2824
2825 StoreHasCrossOriginOpenerPolicyMismatch(false);
2826 if (!StaticPrefs::browser_tabs_remote_useCrossOriginOpenerPolicy()) {
2827 return NS_OK;
2828 }
2829
2830 // Only consider Cross-Origin-Opener-Policy for toplevel document loads.
2831 if (mLoadInfo->GetExternalContentPolicyType() !=
2832 ExtContentPolicy::TYPE_DOCUMENT) {
2833 return NS_OK;
2834 }
2835
2836 // Maybe the channel failed and we have no response head?
2837 if (!mResponseHead) {
2838 // Not having a response head is not a hard failure at the point where
2839 // this method is called.
2840 return NS_OK;
2841 }
2842
2843 RefPtr<mozilla::dom::BrowsingContext> ctx;
2844 mLoadInfo->GetBrowsingContext(getter_AddRefs(ctx));
2845
2846 // In xpcshell-tests we don't always have a browsingContext
2847 if (!ctx) {
2848 return NS_OK;
2849 }
2850
2851 nsCOMPtr<nsIPrincipal> resultOrigin;
2852 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
2853 this, getter_AddRefs(resultOrigin));
2854
2855 // Get the policy of the active document, and the policy for the result.
2856 nsILoadInfo::CrossOriginOpenerPolicy documentPolicy = ctx->GetOpenerPolicy();
2857 nsILoadInfo::CrossOriginOpenerPolicy resultPolicy =
2858 nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
2859 (void)ComputeCrossOriginOpenerPolicy(documentPolicy, &resultPolicy);
2860 mComputedCrossOriginOpenerPolicy = resultPolicy;
2861
2862 // Add a permission to mark this site as high-value into the permission DB.
2863 if (resultPolicy != nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) {
2864 mozilla::dom::AddHighValuePermission(
2865 resultOrigin, mozilla::dom::kHighValueCOOPPermission);
2866 }
2867
2868 // If bc's popup sandboxing flag set is not empty and potentialCOOP is
2869 // non-null, then navigate bc to a network error and abort these steps.
2870 if (resultPolicy != nsILoadInfo::OPENER_POLICY_UNSAFE_NONE &&
2871 mLoadInfo->GetSandboxFlags()) {
2872 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::ComputeCrossOriginOpenerPolicyMismatch network error "
"for non empty sandboxing and non null COOP"); } } while (0)
2873 "HttpBaseChannel::ComputeCrossOriginOpenerPolicyMismatch network error "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::ComputeCrossOriginOpenerPolicyMismatch network error "
"for non empty sandboxing and non null COOP"); } } while (0)
2874 "for non empty sandboxing and non null COOP"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::ComputeCrossOriginOpenerPolicyMismatch network error "
"for non empty sandboxing and non null COOP"); } } while (0)
;
2875 return NS_ERROR_DOM_COOP_FAILED;
2876 }
2877
2878 // In xpcshell-tests we don't always have a current window global
2879 RefPtr<mozilla::dom::WindowGlobalParent> currentWindowGlobal =
2880 ctx->Canonical()->GetCurrentWindowGlobal();
2881 if (!currentWindowGlobal) {
2882 return NS_OK;
2883 }
2884
2885 // We use the top window principal as the documentOrigin
2886 nsCOMPtr<nsIPrincipal> documentOrigin =
2887 currentWindowGlobal->DocumentPrincipal();
2888
2889 bool compareResult = CompareCrossOriginOpenerPolicies(
2890 documentPolicy, documentOrigin, resultPolicy, resultOrigin);
2891
2892 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
2893 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::HasCrossOriginOpenerPolicyMismatch - " "doc:%d result:%d - compare:%d\n"
, documentPolicy, resultPolicy, compareResult); } } while (0)
2894 ("HttpBaseChannel::HasCrossOriginOpenerPolicyMismatch - "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::HasCrossOriginOpenerPolicyMismatch - " "doc:%d result:%d - compare:%d\n"
, documentPolicy, resultPolicy, compareResult); } } while (0)
2895 "doc:%d result:%d - compare:%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
, "HttpBaseChannel::HasCrossOriginOpenerPolicyMismatch - " "doc:%d result:%d - compare:%d\n"
, documentPolicy, resultPolicy, compareResult); } } while (0)
2896 documentPolicy, resultPolicy, compareResult))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::HasCrossOriginOpenerPolicyMismatch - " "doc:%d result:%d - compare:%d\n"
, documentPolicy, resultPolicy, compareResult); } } while (0)
;
2897 nsAutoCString docOrigin("(null)");
2898 nsCOMPtr<nsIURI> uri = documentOrigin->GetURI();
2899 if (uri) {
2900 uri->GetSpec(docOrigin);
2901 }
2902 nsAutoCString resOrigin("(null)");
2903 uri = resultOrigin->GetURI();
2904 if (uri) {
2905 uri->GetSpec(resOrigin);
2906 }
2907 LOG(("doc origin:%s - res origin: %s\n", docOrigin.get(), resOrigin.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "doc origin:%s - res origin: %s\n", docOrigin.get(), resOrigin
.get()); } } while (0)
;
2908 }
2909
2910 if (compareResult) {
2911 return NS_OK;
2912 }
2913
2914 // If one of the following is false:
2915 // - document's policy is same-origin-allow-popups
2916 // - resultPolicy is null
2917 // - doc is the initial about:blank document
2918 // then we have a mismatch.
2919
2920 if (documentPolicy != nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_ALLOW_POPUPS) {
2921 StoreHasCrossOriginOpenerPolicyMismatch(true);
2922 return NS_OK;
2923 }
2924
2925 if (resultPolicy != nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) {
2926 StoreHasCrossOriginOpenerPolicyMismatch(true);
2927 return NS_OK;
2928 }
2929
2930 if (!currentWindowGlobal->IsInitialDocument()) {
2931 StoreHasCrossOriginOpenerPolicyMismatch(true);
2932 return NS_OK;
2933 }
2934
2935 return NS_OK;
2936}
2937
2938nsresult HttpBaseChannel::ProcessCrossOriginSecurityHeaders() {
2939 StoreProcessCrossOriginSecurityHeadersCalled(true);
2940 nsresult rv = ProcessCrossOriginEmbedderPolicyHeader();
2941 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2942 return rv;
2943 }
2944 rv = ProcessCrossOriginResourcePolicyHeader();
2945 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2946 return rv;
2947 }
2948 return ComputeCrossOriginOpenerPolicyMismatch();
2949}
2950
2951enum class Report { Error, Warning };
2952
2953// Helper Function to report messages to the console when the loaded
2954// script had a wrong MIME type.
2955void ReportMimeTypeMismatch(HttpBaseChannel* aChannel, const char* aMessageName,
2956 nsIURI* aURI, const nsACString& aContentType,
2957 Report report) {
2958 NS_ConvertUTF8toUTF16 spec(aURI->GetSpecOrDefault());
2959 NS_ConvertUTF8toUTF16 contentType(aContentType);
2960
2961 aChannel->LogMimeTypeMismatch(nsCString(aMessageName),
2962 report == Report::Warning, spec, contentType);
2963}
2964
2965// Check and potentially enforce X-Content-Type-Options: nosniff
2966nsresult ProcessXCTO(HttpBaseChannel* aChannel, nsIURI* aURI,
2967 nsHttpResponseHead* aResponseHead,
2968 nsILoadInfo* aLoadInfo) {
2969 if (!aURI || !aResponseHead || !aLoadInfo) {
2970 // if there is no uri, no response head or no loadInfo, then there is
2971 // nothing to do
2972 return NS_OK;
2973 }
2974
2975 // 1) Query the XCTO header and check if 'nosniff' is the first value.
2976 nsAutoCString contentTypeOptionsHeader;
2977 if (!aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader)) {
2978 // if failed to get XCTO header, then there is nothing to do.
2979 return NS_OK;
2980 }
2981
2982 // let's compare the header (ignoring case)
2983 // e.g. "NoSniFF" -> "nosniff"
2984 // if it's not 'nosniff' then there is nothing to do here
2985 if (!contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) {
2986 // since we are getting here, the XCTO header was sent;
2987 // a non matching value most likely means a mistake happenend;
2988 // e.g. sending 'nosnif' instead of 'nosniff', let's log a warning.
2989 AutoTArray<nsString, 1> params;
2990 CopyUTF8toUTF16(contentTypeOptionsHeader, *params.AppendElement());
2991 RefPtr<dom::Document> doc;
2992 aLoadInfo->GetLoadingDocument(getter_AddRefs(doc));
2993 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "XCTO"_ns, doc,
2994 PropertiesFile::SECURITY_PROPERTIES,
2995 "XCTOHeaderValueMissing", params);
2996 return NS_OK;
2997 }
2998
2999 // 2) Query the content type from the channel
3000 nsAutoCString contentType;
3001 aResponseHead->ContentType(contentType);
3002
3003 // 3) Compare the expected MIME type with the actual type
3004 if (aLoadInfo->GetExternalContentPolicyType() ==
3005 ExtContentPolicy::TYPE_STYLESHEET) {
3006 if (contentType.EqualsLiteral(TEXT_CSS"text/css")) {
3007 return NS_OK;
3008 }
3009 ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType,
3010 Report::Error);
3011 return NS_ERROR_CORRUPTED_CONTENT;
3012 }
3013
3014 if (aLoadInfo->GetExternalContentPolicyType() ==
3015 ExtContentPolicy::TYPE_SCRIPT) {
3016 if (nsContentUtils::IsJavascriptMIMEType(
3017 NS_ConvertUTF8toUTF16(contentType))) {
3018 return NS_OK;
3019 }
3020 ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType,
3021 Report::Error);
3022 return NS_ERROR_CORRUPTED_CONTENT;
3023 }
3024
3025 auto policyType = aLoadInfo->GetExternalContentPolicyType();
3026 if (policyType == ExtContentPolicy::TYPE_DOCUMENT ||
3027 policyType == ExtContentPolicy::TYPE_SUBDOCUMENT ||
3028 policyType == ExtContentPolicy::TYPE_OBJECT) {
3029 // If the header XCTO nosniff is set for any browsing context, then
3030 // we set the skipContentSniffing flag on the Loadinfo. Within
3031 // GetMIMETypeFromContent we then bail early and do not do any sniffing.
3032 aLoadInfo->SetSkipContentSniffing(true);
3033 return NS_OK;
3034 }
3035
3036 return NS_OK;
3037}
3038
3039nsresult EnsureMIMEOfJSONModule(HttpBaseChannel* aChannel, nsIURI* aURI,
3040 nsHttpResponseHead* aResponseHead,
3041 nsILoadInfo* aLoadInfo) {
3042 if (!aURI || !aResponseHead || !aLoadInfo) {
3043 // if there is no uri, no response head or no loadInfo, then there is
3044 // nothing to do
3045 return NS_OK;
3046 }
3047
3048 if (aLoadInfo->GetExternalContentPolicyType() !=
3049 ExtContentPolicy::TYPE_JSON) {
3050 // if this is not a JSON load, then there is nothing to do
3051 return NS_OK;
3052 }
3053
3054 nsAutoCString contentType;
3055 aResponseHead->ContentType(contentType);
3056 NS_ConvertUTF8toUTF16 typeString(contentType);
3057
3058 if (nsContentUtils::IsJsonMimeType(typeString)) {
3059 return NS_OK;
3060 }
3061
3062 ReportMimeTypeMismatch(aChannel, "BlockJsonModuleWithWrongMimeType", aURI,
3063 contentType, Report::Error);
3064 return NS_ERROR_CORRUPTED_CONTENT;
3065}
3066
3067// Ensure that a load of type script has correct MIME type
3068nsresult EnsureMIMEOfScript(HttpBaseChannel* aChannel, nsIURI* aURI,
3069 nsHttpResponseHead* aResponseHead,
3070 nsILoadInfo* aLoadInfo) {
3071 if (!aURI || !aResponseHead || !aLoadInfo) {
3072 // if there is no uri, no response head or no loadInfo, then there is
3073 // nothing to do
3074 return NS_OK;
3075 }
3076
3077 if (aLoadInfo->GetExternalContentPolicyType() !=
3078 ExtContentPolicy::TYPE_SCRIPT) {
3079 // if this is not a script load, then there is nothing to do
3080 return NS_OK;
3081 }
3082
3083 nsAutoCString contentType;
3084 aResponseHead->ContentType(contentType);
3085 NS_ConvertUTF8toUTF16 typeString(contentType);
3086
3087 if (nsContentUtils::IsJavascriptMIMEType(typeString)) {
3088 // script load has type script
3089 glean::http::script_block_incorrect_mime
3090 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eJavascript)
3091 .Add();
3092 return NS_OK;
3093 }
3094
3095 const auto internalPolicyType = aLoadInfo->InternalContentPolicyType();
3096 if (internalPolicyType ==
3097 nsIContentPolicy::TYPE_INTERNAL_WORKER_STATIC_MODULE &&
3098 nsContentUtils::IsJsonMimeType(typeString)) {
3099 // script and json are both allowed
3100 glean::http::script_block_incorrect_mime
3101 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextJson)
3102 .Add();
3103 return NS_OK;
3104 }
3105
3106 switch (aLoadInfo->InternalContentPolicyType()) {
3107 case nsIContentPolicy::TYPE_SCRIPT:
3108 case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
3109 case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
3110 case nsIContentPolicy::TYPE_INTERNAL_MODULE:
3111 case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD:
3112 case nsIContentPolicy::TYPE_INTERNAL_CHROMEUTILS_COMPILED_SCRIPT:
3113 case nsIContentPolicy::TYPE_INTERNAL_FRAME_MESSAGEMANAGER_SCRIPT:
3114 glean::http::script_block_incorrect_mime
3115 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eScriptLoad)
3116 .Add();
3117 break;
3118 case nsIContentPolicy::TYPE_INTERNAL_WORKER:
3119 case nsIContentPolicy::TYPE_INTERNAL_WORKER_STATIC_MODULE:
3120 case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
3121 glean::http::script_block_incorrect_mime
3122 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eWorkerLoad)
3123 .Add();
3124 break;
3125 case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
3126 glean::http::script_block_incorrect_mime
3127 .EnumGet(
3128 glean::http::ScriptBlockIncorrectMimeLabel::eServiceworkerLoad)
3129 .Add();
3130 break;
3131 case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
3132 glean::http::script_block_incorrect_mime
3133 .EnumGet(
3134 glean::http::ScriptBlockIncorrectMimeLabel::eImportscriptLoad)
3135 .Add();
3136 break;
3137 case nsIContentPolicy::TYPE_INTERNAL_AUDIOWORKLET:
3138 case nsIContentPolicy::TYPE_INTERNAL_PAINTWORKLET:
3139 glean::http::script_block_incorrect_mime
3140 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eWorkletLoad)
3141 .Add();
3142 break;
3143 default:
3144 MOZ_ASSERT_UNREACHABLE("unexpected script type")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 script type" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected script type" ")"); do
{ MOZ_CrashSequence(__null, 3144); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3145 break;
3146 }
3147
3148 if (aLoadInfo->GetLoadingPrincipal()->IsSameOrigin(aURI)) {
3149 // same origin
3150 glean::http::script_block_incorrect_mime
3151 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eSameOrigin)
3152 .Add();
3153 } else {
3154 bool cors = false;
3155 nsAutoCString corsOrigin;
3156 nsresult rv = aResponseHead->GetHeader(
3157 nsHttp::ResolveAtom("Access-Control-Allow-Origin"_ns), corsOrigin);
3158 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3159 if (corsOrigin.Equals("*")) {
3160 cors = true;
3161 } else {
3162 nsCOMPtr<nsIURI> corsOriginURI;
3163 rv = NS_NewURI(getter_AddRefs(corsOriginURI), corsOrigin);
3164 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3165 if (aLoadInfo->GetLoadingPrincipal()->IsSameOrigin(corsOriginURI)) {
3166 cors = true;
3167 }
3168 }
3169 }
3170 }
3171 if (cors) {
3172 // cors origin
3173 glean::http::script_block_incorrect_mime
3174 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eCorsOrigin)
3175 .Add();
3176 } else {
3177 // cross origin
3178 glean::http::script_block_incorrect_mime
3179 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eCrossOrigin)
3180 .Add();
3181 }
3182 }
3183
3184 bool block = false;
3185 if (StringBeginsWith(contentType, "image/"_ns)) {
3186 // script load has type image
3187 glean::http::script_block_incorrect_mime
3188 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eImage)
3189 .Add();
3190 block = true;
3191 } else if (StringBeginsWith(contentType, "audio/"_ns)) {
3192 // script load has type audio
3193 glean::http::script_block_incorrect_mime
3194 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eAudio)
3195 .Add();
3196 block = true;
3197 } else if (StringBeginsWith(contentType, "video/"_ns)) {
3198 // script load has type video
3199 glean::http::script_block_incorrect_mime
3200 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eVideo)
3201 .Add();
3202 block = true;
3203 } else if (StringBeginsWith(contentType, "text/csv"_ns)) {
3204 // script load has type text/csv
3205 glean::http::script_block_incorrect_mime
3206 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextCsv)
3207 .Add();
3208 block = true;
3209 }
3210
3211 if (block) {
3212 ReportMimeTypeMismatch(aChannel, "BlockScriptWithWrongMimeType2", aURI,
3213 contentType, Report::Error);
3214 return NS_ERROR_CORRUPTED_CONTENT;
3215 }
3216
3217 if (StringBeginsWith(contentType, "text/plain"_ns)) {
3218 // script load has type text/plain
3219 glean::http::script_block_incorrect_mime
3220 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextPlain)
3221 .Add();
3222 } else if (StringBeginsWith(contentType, "text/xml"_ns)) {
3223 // script load has type text/xml
3224 glean::http::script_block_incorrect_mime
3225 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextXml)
3226 .Add();
3227 } else if (StringBeginsWith(contentType, "application/octet-stream"_ns)) {
3228 // script load has type application/octet-stream
3229 glean::http::script_block_incorrect_mime
3230 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eAppOctetStream)
3231 .Add();
3232 } else if (StringBeginsWith(contentType, "application/xml"_ns)) {
3233 // script load has type application/xml
3234 glean::http::script_block_incorrect_mime
3235 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eAppXml)
3236 .Add();
3237 } else if (StringBeginsWith(contentType, "application/json"_ns)) {
3238 // script load has type application/json
3239 glean::http::script_block_incorrect_mime
3240 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eAppJson)
3241 .Add();
3242 } else if (StringBeginsWith(contentType, "text/json"_ns)) {
3243 // script load has type text/json
3244 glean::http::script_block_incorrect_mime
3245 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextJson)
3246 .Add();
3247 } else if (StringBeginsWith(contentType, "text/html"_ns)) {
3248 // script load has type text/html
3249 glean::http::script_block_incorrect_mime
3250 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextHtml)
3251 .Add();
3252 } else if (contentType.IsEmpty()) {
3253 // script load has no type
3254 glean::http::script_block_incorrect_mime
3255 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eEmpty)
3256 .Add();
3257 } else {
3258 // script load has unknown type
3259 glean::http::script_block_incorrect_mime
3260 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eUnknown)
3261 .Add();
3262 }
3263
3264 nsContentPolicyType internalType = aLoadInfo->InternalContentPolicyType();
3265
3266 // We restrict importScripts() in worker code to JavaScript MIME types.
3267 if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS) {
3268 ReportMimeTypeMismatch(aChannel, "BlockImportScriptsWithWrongMimeType",
3269 aURI, contentType, Report::Error);
3270 return NS_ERROR_CORRUPTED_CONTENT;
3271 }
3272
3273 if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER_STATIC_MODULE) {
3274#ifdef NIGHTLY_BUILD1
3275 if (StaticPrefs::javascript_options_experimental_wasm_esm_integration()) {
3276 if (nsContentUtils::HasWasmMimeTypeEssence(typeString)) {
3277 return NS_OK;
3278 }
3279 }
3280#endif
3281 ReportMimeTypeMismatch(aChannel, "BlockModuleWithWrongMimeType", aURI,
3282 contentType, Report::Error);
3283 return NS_ERROR_CORRUPTED_CONTENT;
3284 }
3285
3286 if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
3287 internalType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER) {
3288 // Do not block the load if the feature is not enabled.
3289 if (!StaticPrefs::security_block_Worker_with_wrong_mime()) {
3290 return NS_OK;
3291 }
3292
3293#ifdef NIGHTLY_BUILD1
3294 if (StaticPrefs::javascript_options_experimental_wasm_esm_integration()) {
3295 if (nsContentUtils::HasWasmMimeTypeEssence(typeString)) {
3296 return NS_OK;
3297 }
3298 }
3299#endif
3300
3301 ReportMimeTypeMismatch(aChannel, "BlockWorkerWithWrongMimeType", aURI,
3302 contentType, Report::Error);
3303 return NS_ERROR_CORRUPTED_CONTENT;
3304 }
3305
3306 // ES6 modules require a strict MIME type check.
3307 if (internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE ||
3308 internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD) {
3309#ifdef NIGHTLY_BUILD1
3310 if (StaticPrefs::javascript_options_experimental_wasm_esm_integration()) {
3311 if (nsContentUtils::HasWasmMimeTypeEssence(typeString)) {
3312 return NS_OK;
3313 }
3314 }
3315#endif
3316
3317 ReportMimeTypeMismatch(aChannel, "BlockModuleWithWrongMimeType", aURI,
3318 contentType, Report::Error);
3319 return NS_ERROR_CORRUPTED_CONTENT;
3320 }
3321
3322 return NS_OK;
3323}
3324
3325// Warn when a load of type script uses a wrong MIME type and
3326// wasn't blocked by EnsureMIMEOfScript or ProcessXCTO.
3327void WarnWrongMIMEOfScript(HttpBaseChannel* aChannel, nsIURI* aURI,
3328 nsHttpResponseHead* aResponseHead,
3329 nsILoadInfo* aLoadInfo) {
3330 if (!aURI || !aResponseHead || !aLoadInfo) {
3331 // If there is no uri, no response head or no loadInfo, then there is
3332 // nothing to do.
3333 return;
3334 }
3335
3336 if (aLoadInfo->GetExternalContentPolicyType() !=
3337 ExtContentPolicy::TYPE_SCRIPT) {
3338 // If this is not a script load, then there is nothing to do.
3339 return;
3340 }
3341
3342 bool succeeded;
3343 MOZ_ALWAYS_SUCCEEDS(aChannel->GetRequestSucceeded(&succeeded))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(aChannel->GetRequestSucceeded(&succeeded))), 1)))), 1
))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(aChannel->GetRequestSucceeded(&succeeded))"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3343
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(aChannel->GetRequestSucceeded(&succeeded))"
")"); do { MOZ_CrashSequence(__null, 3343); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3344 if (!succeeded) {
3345 // Do not warn for failed loads: HTTP error pages are usually in HTML.
3346 return;
3347 }
3348
3349 nsAutoCString contentType;
3350 aResponseHead->ContentType(contentType);
3351 NS_ConvertUTF8toUTF16 typeString(contentType);
3352
3353 if (nsContentUtils::IsJavascriptMIMEType(typeString)) {
3354 return;
3355 }
3356
3357#ifdef NIGHTLY_BUILD1
3358 if (StaticPrefs::javascript_options_experimental_wasm_esm_integration()) {
3359 if (nsContentUtils::HasWasmMimeTypeEssence(typeString)) {
3360 return;
3361 }
3362 }
3363#endif
3364
3365 ReportMimeTypeMismatch(aChannel, "WarnScriptWithWrongMimeType", aURI,
3366 contentType, Report::Warning);
3367}
3368
3369nsresult HttpBaseChannel::ValidateMIMEType() {
3370 nsresult rv = EnsureMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo);
3371 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3372 return rv;
3373 }
3374
3375 rv = EnsureMIMEOfJSONModule(this, mURI, mResponseHead.get(), mLoadInfo);
3376 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3377 return rv;
3378 }
3379
3380 rv = ProcessXCTO(this, mURI, mResponseHead.get(), mLoadInfo);
3381 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3382 return rv;
3383 }
3384
3385 WarnWrongMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo);
3386 return NS_OK;
3387}
3388
3389bool HttpBaseChannel::ShouldFilterOpaqueResponse(
3390 OpaqueResponseFilterFetch aFilterType) const {
3391 MOZ_ASSERT(ShouldBlockOpaqueResponse())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ShouldBlockOpaqueResponse())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ShouldBlockOpaqueResponse())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ShouldBlockOpaqueResponse()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3391
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ShouldBlockOpaqueResponse()"
")"); do { MOZ_CrashSequence(__null, 3391); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3392
3393 if (!mLoadInfo || ConfiguredFilterFetchResponseBehaviour() != aFilterType) {
3394 return false;
3395 }
3396
3397 // We should filter a response in the parent if it is opaque and is the result
3398 // of a fetch() function from the Fetch specification.
3399 return mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_FETCH;
3400}
3401
3402bool HttpBaseChannel::ShouldBlockOpaqueResponse() const {
3403 if (!mURI || !mResponseHead || !mLoadInfo) {
3404 // if there is no uri, no response head or no loadInfo, then there is
3405 // nothing to do
3406 LOGORB("No block: no mURI, mResponseHead, or mLoadInfo");
3407 return false;
3408 }
3409
3410 nsCOMPtr<nsIPrincipal> principal = mLoadInfo->GetLoadingPrincipal();
3411 if (!principal || principal->IsSystemPrincipal()) {
3412 // If it's a top-level load or a system principal, then there is nothing to
3413 // do.
3414 LOGORB("No block: top-level load or system principal");
3415 return false;
3416 }
3417
3418 // Check if the response is a opaque response, which means requestMode should
3419 // be RequestMode::No_cors and responseType should be ResponseType::Opaque.
3420 nsContentPolicyType contentPolicy = mLoadInfo->InternalContentPolicyType();
3421
3422 // Skip the RequestMode would be RequestMode::Navigate
3423 if (contentPolicy == nsIContentPolicy::TYPE_DOCUMENT ||
3424 contentPolicy == nsIContentPolicy::TYPE_SUBDOCUMENT ||
3425 contentPolicy == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
3426 contentPolicy == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
3427 // Skip the RequestMode would be RequestMode::Same_origin
3428 contentPolicy == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
3429 contentPolicy == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER) {
3430 return false;
3431 }
3432
3433 uint32_t securityMode = mLoadInfo->GetSecurityMode();
3434 // Skip when RequestMode would not be RequestMode::no_cors
3435 if (securityMode !=
3436 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT &&
3437 securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL) {
3438 LOGORB("No block: not no_cors requests");
3439 return false;
3440 }
3441
3442 // Only continue when ResponseType would be ResponseType::Opaque
3443 if (mLoadInfo->GetTainting() != mozilla::LoadTainting::Opaque) {
3444 LOGORB("No block: not opaque response");
3445 return false;
3446 }
3447
3448 auto extContentPolicyType = mLoadInfo->GetExternalContentPolicyType();
3449 if (extContentPolicyType == ExtContentPolicy::TYPE_OBJECT ||
3450 extContentPolicyType == ExtContentPolicy::TYPE_WEBSOCKET ||
3451 extContentPolicyType == ExtContentPolicy::TYPE_SAVEAS_DOWNLOAD) {
3452 LOGORB("No block: object || websocket request || save as download");
3453 return false;
3454 }
3455
3456 // Exclude no_cors System XHR
3457 if (extContentPolicyType == ExtContentPolicy::TYPE_XMLHTTPREQUEST) {
3458 if (securityMode ==
3459 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT) {
3460 LOGORB("No block: System XHR");
3461 return false;
3462 }
3463 }
3464
3465 // Exclude no_cors web-identity
3466 if (extContentPolicyType == ExtContentPolicy::TYPE_WEB_IDENTITY) {
3467 if (securityMode ==
3468 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT) {
3469 printf("Allowing ORB for web-identity\n");
3470 LOGORB("No block: System web-identity");
3471 return false;
3472 }
3473 }
3474
3475 uint32_t httpsOnlyStatus = mLoadInfo->GetHttpsOnlyStatus();
3476 if (httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_BYPASS_ORB) {
3477 LOGORB("No block: HTTPS_ONLY_BYPASS_ORB");
3478 return false;
3479 }
3480
3481 return true;
3482}
3483
3484OpaqueResponse HttpBaseChannel::BlockOrFilterOpaqueResponse(
3485 OpaqueResponseBlocker* aORB, const nsAString& aReason,
3486 const OpaqueResponseBlockedTelemetryReason aTelemetryReason,
3487 const char* aFormat, ...) {
3488 NimbusFeatures::RecordExposureEvent("opaqueResponseBlocking"_ns, true);
3489
3490 const bool shouldFilter =
3491 ShouldFilterOpaqueResponse(OpaqueResponseFilterFetch::BlockedByORB);
3492
3493 if (MOZ_UNLIKELY(MOZ_LOG_TEST(GetORBLog(), LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(GetORBLog(), LogLevel::Debug)), 0))), 0))
) {
3494 va_list ap;
3495 va_start(ap, aFormat)__builtin_va_start(ap, aFormat);
3496 nsVprintfCString logString(aFormat, ap);
3497 va_end(ap)__builtin_va_end(ap);
3498
3499 LOGORB("%s: %s", shouldFilter ? "Filtered" : "Blocked", logString.get());
3500 }
3501
3502 if (shouldFilter) {
3503 glean::orb::block_initiator
3504 .EnumGet(glean::orb::BlockInitiatorLabel::eFilteredFetch)
3505 .Add();
3506 // The existence of `mORB` depends on `BlockOrFilterOpaqueResponse` being
3507 // called before or after sniffing has completed.
3508 // Another requirement is that `OpaqueResponseFilter` must come after
3509 // `OpaqueResponseBlocker`, which is why in the case of having an
3510 // `OpaqueResponseBlocker` we let it handle creating an
3511 // `OpaqueResponseFilter`.
3512 if (aORB) {
3513 MOZ_DIAGNOSTIC_ASSERT(!mORB || aORB == mORB)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mORB || aORB == mORB)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mORB || aORB == mORB))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!mORB || aORB == mORB"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3513
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mORB || aORB == mORB"
")"); do { MOZ_CrashSequence(__null, 3513); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3514 aORB->FilterResponse();
3515 } else {
3516 mListener = new OpaqueResponseFilter(mListener);
3517 }
3518 return OpaqueResponse::Allow;
3519 }
3520
3521 LogORBError(aReason, aTelemetryReason);
3522 return OpaqueResponse::Block;
3523}
3524
3525dom::NoCorsMediaRequestState HttpBaseChannel::NoCorsMediaRequestState() {
3526 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3526
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3526); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3527
3528 if (!mLoadInfo->GetIsMediaRequest()) {
3529 return dom::NoCorsMediaRequestState::NotAvailable;
3530 }
3531
3532 RefPtr<dom::WindowGlobalParent> wgp =
3533 dom::WindowGlobalParent::GetByInnerWindowId(
3534 mLoadInfo->GetInnerWindowID());
3535 if (!wgp || wgp->IsDiscarded()) {
3536 return dom::NoCorsMediaRequestState::NotAvailable;
3537 }
3538
3539 return wgp->NoCorsMediaRequestState(mURI);
3540}
3541
3542void HttpBaseChannel::RecordSubsequentNoCorsRequestState() {
3543 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3543
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3543); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3544 MOZ_ASSERT(mLoadInfo->GetIsMediaRequest())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetIsMediaRequest())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo->GetIsMediaRequest
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLoadInfo->GetIsMediaRequest()", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3544); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetIsMediaRequest()"
")"); do { MOZ_CrashSequence(__null, 3544); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3545
3546 RefPtr<dom::WindowGlobalParent> wgp =
3547 dom::WindowGlobalParent::GetByInnerWindowId(
3548 mLoadInfo->GetInnerWindowID());
3549 if (!wgp || wgp->IsDiscarded()) {
3550 return;
3551 }
3552
3553 wgp->RecordSubsequentNoCorsRequestState(mURI);
3554}
3555
3556// The specification for ORB is currently being written:
3557// https://whatpr.org/fetch/1442.html#orb-algorithm
3558// The `opaque-response-safelist check` is implemented in:
3559// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff`
3560// * `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
3561// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff`
3562// * `OpaqueResponseBlocker::ValidateJavaScript`
3563OpaqueResponse
3564HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff() {
3565 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3565
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3565); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3566
3567 // https://whatpr.org/fetch/1442.html#http-fetch, step 6.4
3568 if (!ShouldBlockOpaqueResponse()) {
3569 return OpaqueResponse::Allow;
3570 }
3571
3572 // Regardless of if ORB is enabled or not, we check if we should filter the
3573 // response in the parent. This way data won't reach a content process that
3574 // will create a filtered `Response` object. This is enabled when
3575 // 'browser.opaqueResponseBlocking.filterFetchResponse' is
3576 // `OpaqueResponseFilterFetch::All`.
3577 // See https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
3578 if (ShouldFilterOpaqueResponse(OpaqueResponseFilterFetch::All)) {
3579 mListener = new OpaqueResponseFilter(mListener);
3580
3581 // If we're filtering a response in the parent, there will be no data to
3582 // determine if it should be blocked or not so the only option we have is to
3583 // allow it.
3584 return OpaqueResponse::Allow;
3585 }
3586
3587 if (!mCachedOpaqueResponseBlockingPref) {
3588 return OpaqueResponse::Allow;
3589 }
3590
3591 // If ORB is enabled, we check if we should filter the response in the parent.
3592 // This way data won't reach a content process that will create a filtered
3593 // `Response` object. We allow ORB to determine if the response should be
3594 // blocked or filtered, but regardless no data should reach the content
3595 // process. This is enabled when
3596 // 'browser.opaqueResponseBlocking.filterFetchResponse' is
3597 // `OpaqueResponseFilterFetch::AllowedByORB`.
3598 // See https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
3599 if (ShouldFilterOpaqueResponse(OpaqueResponseFilterFetch::AllowedByORB)) {
3600 mListener = new OpaqueResponseFilter(mListener);
3601 }
3602
3603 glean::opaque_response_blocking::cross_origin_opaque_response_count.Add(1);
3604
3605 PROFILER_MARKER_TEXT("ORB safelist check", NETWORK, {}, "Before sniff"_ns)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ORB safelist check", ::geckoprofiler::category::NETWORK, {}
, ::geckoprofiler::markers::TextMarker{}, "Before sniff"_ns);
} } while (false); } while (false)
;
3606
3607 // https://whatpr.org/fetch/1442.html#orb-algorithm
3608 // Step 1
3609 nsAutoCString contentType;
3610 mResponseHead->ContentType(contentType);
3611
3612 // Step 2
3613 nsAutoCString contentTypeOptionsHeader;
3614 bool nosniff =
3615 mResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader) &&
3616 contentTypeOptionsHeader.EqualsIgnoreCase("nosniff");
3617
3618 // Step 3
3619 switch (GetOpaqueResponseBlockedReason(contentType, mResponseHead->Status(),
3620 nosniff)) {
3621 case OpaqueResponseBlockedReason::ALLOWED_SAFE_LISTED:
3622 // Step 3.1
3623 return OpaqueResponse::Allow;
3624 case OpaqueResponseBlockedReason::ALLOWED_SAFE_LISTED_SPEC_BREAKING:
3625 LOGORB("Allowed %s in a spec breaking way", contentType.get());
3626 return OpaqueResponse::Allow;
3627 case OpaqueResponseBlockedReason::BLOCKED_BLOCKLISTED_NEVER_SNIFFED:
3628 return BlockOrFilterOpaqueResponse(
3629 mORB, u"mimeType is an opaque-blocklisted-never-sniffed MIME type"_ns,
3630 OpaqueResponseBlockedTelemetryReason::eMimeNeverSniffed,
3631 "BLOCKED_BLOCKLISTED_NEVER_SNIFFED");
3632 case OpaqueResponseBlockedReason::BLOCKED_206_AND_BLOCKLISTED:
3633 // Step 3.3
3634 return BlockOrFilterOpaqueResponse(
3635 mORB,
3636 u"response's status is 206 and mimeType is an opaque-blocklisted MIME type"_ns,
3637 OpaqueResponseBlockedTelemetryReason::eResp206Blclisted,
3638 "BLOCKED_206_AND_BLOCKEDLISTED");
3639 case OpaqueResponseBlockedReason::
3640 BLOCKED_NOSNIFF_AND_EITHER_BLOCKLISTED_OR_TEXTPLAIN:
3641 // Step 3.4
3642 return BlockOrFilterOpaqueResponse(
3643 mORB,
3644 u"nosniff is true and mimeType is an opaque-blocklisted MIME type or its essence is 'text/plain'"_ns,
3645 OpaqueResponseBlockedTelemetryReason::eNosniffBlcOrTextp,
3646 "BLOCKED_NOSNIFF_AND_EITHER_BLOCKLISTED_OR_TEXTPLAIN");
3647 default:
3648 break;
3649 }
3650
3651 // Step 4
3652 // If it's a media subsequent request, we assume that it will only be made
3653 // after a successful initial request.
3654 if (NoCorsMediaRequestState() == dom::NoCorsMediaRequestState::Subsequent) {
3655 return OpaqueResponse::Allow;
3656 }
3657
3658 // Step 5
3659 if (mResponseHead->Status() == 206 &&
3660 !IsFirstPartialResponse(*mResponseHead)) {
3661 return BlockOrFilterOpaqueResponse(
3662 mORB, u"response status is 206 and not first partial response"_ns,
3663 OpaqueResponseBlockedTelemetryReason::eResp206Blclisted,
3664 "Is not a valid partial response given 0");
3665 }
3666
3667 // Setup for steps 6, 7, 8 and 10.
3668 // Steps 6 and 7 are handled by the sniffer framework.
3669 // Steps 8 and 10 by are handled by
3670 // `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
3671 if (mLoadFlags & nsIChannel::LOAD_CALL_CONTENT_SNIFFERS) {
3672 mSnifferCategoryType = SnifferCategoryType::All;
3673 } else {
3674 mSnifferCategoryType = SnifferCategoryType::OpaqueResponseBlocking;
3675 }
3676
3677 mLoadFlags |= (nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
3678 nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE);
3679
3680 // Install an input stream listener that performs ORB checks that depend on
3681 // inspecting the incoming data. It is crucial that `OnStartRequest` is called
3682 // on this listener either after sniffing is completed or that we skip
3683 // sniffing, otherwise `OpaqueResponseBlocker` will allow responses that it
3684 // shouldn't.
3685 mORB = new OpaqueResponseBlocker(mListener, this, contentType, nosniff);
3686 mListener = mORB;
3687
3688 nsAutoCString contentEncoding;
3689 nsresult rv =
3690 mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
3691
3692 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !contentEncoding.IsEmpty()) {
3693 return OpaqueResponse::SniffCompressed;
3694 }
3695 mLoadFlags |= (nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
3696 nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE);
3697 return OpaqueResponse::Sniff;
3698}
3699
3700// The specification for ORB is currently being written:
3701// https://whatpr.org/fetch/1442.html#orb-algorithm
3702// The `opaque-response-safelist check` is implemented in:
3703// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff`
3704// * `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
3705// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff`
3706// * `OpaqueResponseBlocker::ValidateJavaScript`
3707OpaqueResponse HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff(
3708 const nsACString& aContentType, bool aNoSniff) {
3709 PROFILER_MARKER_TEXT("ORB safelist check", NETWORK, {}, "After sniff"_ns)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ORB safelist check", ::geckoprofiler::category::NETWORK, {}
, ::geckoprofiler::markers::TextMarker{}, "After sniff"_ns); }
} while (false); } while (false)
;
3710
3711 // https://whatpr.org/fetch/1442.html#orb-algorithm
3712 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3712
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3712); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3713 MOZ_ASSERT(mCachedOpaqueResponseBlockingPref)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCachedOpaqueResponseBlockingPref)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCachedOpaqueResponseBlockingPref
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mCachedOpaqueResponseBlockingPref", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedOpaqueResponseBlockingPref"
")"); do { MOZ_CrashSequence(__null, 3713); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3714
3715 // Step 9
3716 if (NoCorsMediaRequestState() != dom::NoCorsMediaRequestState::NotAvailable) {
3717 return BlockOrFilterOpaqueResponse(
3718 mORB, u"after sniff: media request"_ns,
3719 OpaqueResponseBlockedTelemetryReason::eAfterSniffMedia,
3720 "media request");
3721 }
3722
3723 // Step 11
3724 if (aNoSniff) {
3725 return BlockOrFilterOpaqueResponse(
3726 mORB, u"after sniff: nosniff is true"_ns,
3727 OpaqueResponseBlockedTelemetryReason::eAfterSniffNosniff, "nosniff");
3728 }
3729
3730 // Step 12
3731 if (mResponseHead &&
3732 (mResponseHead->Status() < 200 || mResponseHead->Status() > 299)) {
3733 return BlockOrFilterOpaqueResponse(
3734 mORB, u"after sniff: status code is not in allowed range"_ns,
3735 OpaqueResponseBlockedTelemetryReason::eAfterSniffStaCode,
3736 "status code (%d) is not allowed", mResponseHead->Status());
3737 }
3738
3739 // Step 13
3740 if (!mResponseHead || aContentType.IsEmpty()) {
3741 LOGORB("Allowed: mimeType is failure");
3742 return OpaqueResponse::Allow;
3743 }
3744
3745 // Step 14
3746 if (StringBeginsWith(aContentType, "image/"_ns) ||
3747 StringBeginsWith(aContentType, "video/"_ns) ||
3748 StringBeginsWith(aContentType, "audio/"_ns)) {
3749 return BlockOrFilterOpaqueResponse(
3750 mORB,
3751 u"after sniff: content-type declares image/video/audio, but sniffing fails"_ns,
3752 OpaqueResponseBlockedTelemetryReason::eAfterSniffCtFail,
3753 "ContentType is image/video/audio");
3754 }
3755
3756 return OpaqueResponse::Sniff;
3757}
3758
3759bool HttpBaseChannel::NeedOpaqueResponseAllowedCheckAfterSniff() const {
3760 RefPtr<OpaqueResponseBlocker> orb(mORB);
3761 return orb ? orb->IsSniffing() : false;
3762}
3763
3764void HttpBaseChannel::BlockOpaqueResponseAfterSniff(
3765 const nsAString& aReason,
3766 const OpaqueResponseBlockedTelemetryReason aTelemetryReason) {
3767 MOZ_DIAGNOSTIC_ASSERT(mORB)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mORB)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mORB))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mORB", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3767); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mORB"
")"); do { MOZ_CrashSequence(__null, 3767); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3768 LogORBError(aReason, aTelemetryReason);
3769 RefPtr<OpaqueResponseBlocker> orb(mORB);
3770 orb->BlockResponse(this, NS_ERROR_DOM_NETWORK_ERR);
3771}
3772
3773void HttpBaseChannel::AllowOpaqueResponseAfterSniff() {
3774 MOZ_DIAGNOSTIC_ASSERT(mORB)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mORB)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mORB))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mORB", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3774); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mORB"
")"); do { MOZ_CrashSequence(__null, 3774); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3775 RefPtr<OpaqueResponseBlocker> orb(mORB);
3776 orb->AllowResponse();
3777}
3778
3779void HttpBaseChannel::SetChannelBlockedByOpaqueResponse() {
3780 mChannelBlockedByOpaqueResponse = true;
3781
3782 RefPtr<dom::BrowsingContext> browsingContext =
3783 dom::BrowsingContext::GetCurrentTopByBrowserId(mBrowserId);
3784 if (!browsingContext) {
3785 return;
3786 }
3787
3788 dom::WindowContext* windowContext = browsingContext->GetTopWindowContext();
3789 if (windowContext) {
3790 windowContext->Canonical()->SetShouldReportHasBlockedOpaqueResponse(
3791 mLoadInfo->InternalContentPolicyType());
3792 }
3793}
3794
3795nsresult HttpBaseChannel::SetCookieHeaders(
3796 const nsTArray<nsCString>& aCookieHeaders) {
3797 if (mLoadFlags & LOAD_ANONYMOUS) return NS_OK;
3798
3799 // The loadGroup of the channel in the parent process could be null in the
3800 // XPCShell content process test, see test_cookiejars_wrap.js. In this case,
3801 // we cannot explicitly set the loadGroup for the parent channel because it's
3802 // created from the content process. To workaround this, we add a testing pref
3803 // to skip this check.
3804 if (!StaticPrefs::
3805 network_cookie_skip_browsing_context_check_in_parent_for_testing() &&
3806 IsBrowsingContextDiscarded()) {
3807 return NS_OK;
3808 }
3809
3810 // empty header isn't an error
3811 if (aCookieHeaders.IsEmpty()) {
3812 return NS_OK;
3813 }
3814
3815 nsICookieService* cs = gHttpHandler->GetCookieService();
3816 NS_ENSURE_TRUE(cs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(cs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "cs" ") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3816); return NS_ERROR_FAILURE; } } while (false)
;
3817
3818 for (const nsCString& cookieHeader : aCookieHeaders) {
3819 nsresult rv = cs->SetCookieStringFromHttp(mURI, cookieHeader, this);
3820 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3820); return rv; } } while (false)
;
3821 }
3822
3823 return NS_OK;
3824}
3825
3826NS_IMETHODIMPnsresult
3827HttpBaseChannel::GetThirdPartyFlags(uint32_t* aFlags) {
3828 *aFlags = LoadThirdPartyFlags();
3829 return NS_OK;
3830}
3831
3832NS_IMETHODIMPnsresult
3833HttpBaseChannel::SetThirdPartyFlags(uint32_t aFlags) {
3834 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3834); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3834, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3834); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3834); return NS_ERROR_IN_PROGRESS; } } while (false); do {
if ((__builtin_expect(!!(!(!LoadWasOpened())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadWasOpened()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3834); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
3835
3836 StoreThirdPartyFlags(aFlags);
3837 return NS_OK;
3838}
3839
3840NS_IMETHODIMPnsresult
3841HttpBaseChannel::GetForceAllowThirdPartyCookie(bool* aForce) {
3842 *aForce = !!(LoadThirdPartyFlags() &
3843 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
3844 return NS_OK;
3845}
3846
3847NS_IMETHODIMPnsresult
3848HttpBaseChannel::SetForceAllowThirdPartyCookie(bool aForce) {
3849 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3849); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3849, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3849); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3849); return NS_ERROR_IN_PROGRESS; } } while (false); do {
if ((__builtin_expect(!!(!(!LoadWasOpened())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadWasOpened()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3849); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
3850
3851 if (aForce) {
3852 StoreThirdPartyFlags(LoadThirdPartyFlags() |
3853 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
3854 } else {
3855 StoreThirdPartyFlags(LoadThirdPartyFlags() &
3856 ~nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
3857 }
3858
3859 return NS_OK;
3860}
3861
3862NS_IMETHODIMPnsresult
3863HttpBaseChannel::GetCanceled(bool* aCanceled) {
3864 *aCanceled = mCanceled;
3865 return NS_OK;
3866}
3867
3868NS_IMETHODIMPnsresult
3869HttpBaseChannel::GetChannelIsForDownload(bool* aChannelIsForDownload) {
3870 *aChannelIsForDownload = LoadChannelIsForDownload();
3871 return NS_OK;
3872}
3873
3874NS_IMETHODIMPnsresult
3875HttpBaseChannel::SetChannelIsForDownload(bool aChannelIsForDownload) {
3876 StoreChannelIsForDownload(aChannelIsForDownload);
3877 return NS_OK;
3878}
3879
3880NS_IMETHODIMPnsresult
3881HttpBaseChannel::SetCacheKeysRedirectChain(nsTArray<nsCString>* cacheKeys) {
3882 auto RedirectedCachekeys = mRedirectedCachekeys.Lock();
3883 auto& ref = RedirectedCachekeys.ref();
3884 ref = WrapUnique(cacheKeys);
3885 return NS_OK;
3886}
3887
3888NS_IMETHODIMPnsresult
3889HttpBaseChannel::GetLocalAddress(nsACString& addr) {
3890 if (mSelfAddr.raw.family == PR_AF_UNSPEC0) return NS_ERROR_NOT_AVAILABLE;
3891
3892 mSelfAddr.ToString(addr);
3893
3894 return NS_OK;
3895}
3896
3897NS_IMETHODIMPnsresult
3898HttpBaseChannel::TakeAllSecurityMessages(
3899 nsCOMArray<nsISecurityConsoleMessage>& aMessages) {
3900 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3900
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 3900); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3901
3902 aMessages.Clear();
3903 for (const auto& pair : mSecurityConsoleMessages) {
3904 nsresult rv;
3905 nsCOMPtr<nsISecurityConsoleMessage> message =
3906 do_CreateInstance(NS_SECURITY_CONSOLE_MESSAGE_CONTRACTID"@mozilla.org/securityconsole/message;1", &rv);
3907 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3907); return rv; } } while (false)
;
3908
3909 message->SetTag(pair.first);
3910 message->SetCategory(pair.second);
3911 aMessages.AppendElement(message);
3912 }
3913
3914 MOZ_ASSERT(mSecurityConsoleMessages.Length() == aMessages.Length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSecurityConsoleMessages.Length() == aMessages.Length
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mSecurityConsoleMessages.Length() == aMessages.Length
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mSecurityConsoleMessages.Length() == aMessages.Length()", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSecurityConsoleMessages.Length() == aMessages.Length()"
")"); do { MOZ_CrashSequence(__null, 3914); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3915 mSecurityConsoleMessages.Clear();
3916
3917 return NS_OK;
3918}
3919
3920/* Please use this method with care. This can cause the message
3921 * queue to grow large and cause the channel to take up a lot
3922 * of memory. Use only static string messages and do not add
3923 * server side data to the queue, as that can be large.
3924 * Add only a limited number of messages to the queue to keep
3925 * the channel size down and do so only in rare erroneous situations.
3926 * More information can be found here:
3927 * https://bugzilla.mozilla.org/show_bug.cgi?id=846918
3928 */
3929nsresult HttpBaseChannel::AddSecurityMessage(
3930 const nsAString& aMessageTag, const nsAString& aMessageCategory) {
3931 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3931
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 3931); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3932
3933 nsresult rv;
3934
3935 // nsSecurityConsoleMessage is not thread-safe refcounted.
3936 // Delay the object construction until requested.
3937 // See TakeAllSecurityMessages()
3938 std::pair<nsString, nsString> pair(aMessageTag, aMessageCategory);
3939 mSecurityConsoleMessages.AppendElement(std::move(pair));
3940
3941 nsCOMPtr<nsIConsoleService> console(
3942 do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1"));
3943 if (!console) {
3944 return NS_ERROR_FAILURE;
3945 }
3946
3947 nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
3948
3949 auto innerWindowID = loadInfo->GetInnerWindowID();
3950
3951 nsAutoString errorText;
3952 rv = nsContentUtils::GetLocalizedString(
3953 PropertiesFile::SECURITY_PROPERTIES,
3954 NS_ConvertUTF16toUTF8(aMessageTag).get(), errorText);
3955 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3955); return rv; } } while (false)
;
3956
3957 nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1"));
3958 error->InitWithSourceURI(errorText, mURI, 0, 0, nsIScriptError::warningFlag,
3959 NS_ConvertUTF16toUTF8(aMessageCategory),
3960 innerWindowID);
3961
3962 console->LogMessage(error);
3963
3964 return NS_OK;
3965}
3966
3967NS_IMETHODIMPnsresult
3968HttpBaseChannel::GetLocalPort(int32_t* port) {
3969 NS_ENSURE_ARG_POINTER(port)do { if ((__builtin_expect(!!(!(port)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "port" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3969
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3970
3971 if (mSelfAddr.raw.family == PR_AF_INET2) {
3972 *port = (int32_t)ntohs(mSelfAddr.inet.port)__bswap_16 (mSelfAddr.inet.port);
3973 } else if (mSelfAddr.raw.family == PR_AF_INET610) {
3974 *port = (int32_t)ntohs(mSelfAddr.inet6.port)__bswap_16 (mSelfAddr.inet6.port);
3975 } else {
3976 return NS_ERROR_NOT_AVAILABLE;
3977 }
3978
3979 return NS_OK;
3980}
3981
3982NS_IMETHODIMPnsresult
3983HttpBaseChannel::GetRemoteAddress(nsACString& addr) {
3984 if (mPeerAddr.raw.family == PR_AF_UNSPEC0) return NS_ERROR_NOT_AVAILABLE;
3985
3986 mPeerAddr.ToString(addr);
3987
3988 return NS_OK;
3989}
3990
3991NS_IMETHODIMPnsresult
3992HttpBaseChannel::GetRemotePort(int32_t* port) {
3993 NS_ENSURE_ARG_POINTER(port)do { if ((__builtin_expect(!!(!(port)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "port" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 3993
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3994
3995 if (mPeerAddr.raw.family == PR_AF_INET2) {
3996 *port = (int32_t)ntohs(mPeerAddr.inet.port)__bswap_16 (mPeerAddr.inet.port);
3997 } else if (mPeerAddr.raw.family == PR_AF_INET610) {
3998 *port = (int32_t)ntohs(mPeerAddr.inet6.port)__bswap_16 (mPeerAddr.inet6.port);
3999 } else {
4000 return NS_ERROR_NOT_AVAILABLE;
4001 }
4002
4003 return NS_OK;
4004}
4005
4006NS_IMETHODIMPnsresult
4007HttpBaseChannel::HTTPUpgrade(const nsACString& aProtocolName,
4008 nsIHttpUpgradeListener* aListener) {
4009 NS_ENSURE_ARG(!aProtocolName.IsEmpty())do { if ((__builtin_expect(!!(!(!aProtocolName.IsEmpty())), 0
))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!aProtocolName.IsEmpty()"
") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4009); return NS_ERROR_INVALID_ARG; } } while (false)
;
4010 NS_ENSURE_ARG_POINTER(aListener)do { if ((__builtin_expect(!!(!(aListener)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aListener" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4010
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4011
4012 // The protocol name is emitted verbatim into the Upgrade request header, so
4013 // reject anything that could inject additional headers or requests (e.g. an
4014 // embedded CRLF from a compromised child process).
4015 if (!nsHttp::IsReasonableHeaderValue(aProtocolName)) {
4016 return NS_ERROR_ILLEGAL_VALUE;
4017 }
4018
4019 mUpgradeProtocol = aProtocolName;
4020 mUpgradeProtocolCallback = aListener;
4021 return NS_OK;
4022}
4023
4024NS_IMETHODIMPnsresult
4025HttpBaseChannel::GetOnlyConnect(bool* aOnlyConnect) {
4026 NS_ENSURE_ARG_POINTER(aOnlyConnect)do { if ((__builtin_expect(!!(!(aOnlyConnect)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOnlyConnect" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4026); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4027
4028 *aOnlyConnect = mCaps & NS_HTTP_CONNECT_ONLY(1 << 16);
4029 return NS_OK;
4030}
4031
4032NS_IMETHODIMPnsresult
4033HttpBaseChannel::SetConnectOnly(bool aTlsTunnel) {
4034 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4034); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4034, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4034); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4034
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 4034); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
4035
4036 if (!mUpgradeProtocolCallback) {
4037 return NS_ERROR_FAILURE;
4038 }
4039
4040 mCaps |= NS_HTTP_CONNECT_ONLY(1 << 16);
4041 if (aTlsTunnel) {
4042 mCaps |= NS_HTTP_TLS_TUNNEL(1 << 29);
4043 }
4044 mProxyResolveFlags = nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
4045 nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL;
4046 return SetLoadFlags(nsIRequest::INHIBIT_CACHING | nsIChannel::LOAD_ANONYMOUS |
4047 nsIRequest::LOAD_BYPASS_CACHE |
4048 nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
4049}
4050
4051NS_IMETHODIMPnsresult
4052HttpBaseChannel::GetAllowSpdy(bool* aAllowSpdy) {
4053 NS_ENSURE_ARG_POINTER(aAllowSpdy)do { if ((__builtin_expect(!!(!(aAllowSpdy)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowSpdy" ") failed",
nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4053); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4054
4055 *aAllowSpdy = LoadAllowSpdy();
4056 return NS_OK;
4057}
4058
4059NS_IMETHODIMPnsresult
4060HttpBaseChannel::SetAllowSpdy(bool aAllowSpdy) {
4061 StoreAllowSpdy(aAllowSpdy);
4062 return NS_OK;
4063}
4064
4065NS_IMETHODIMPnsresult
4066HttpBaseChannel::GetAllowHttp3(bool* aAllowHttp3) {
4067 NS_ENSURE_ARG_POINTER(aAllowHttp3)do { if ((__builtin_expect(!!(!(aAllowHttp3)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowHttp3" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4067); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4068
4069 *aAllowHttp3 = LoadAllowHttp3();
4070 return NS_OK;
4071}
4072
4073NS_IMETHODIMPnsresult
4074HttpBaseChannel::SetAllowHttp3(bool aAllowHttp3) {
4075 StoreAllowHttp3(aAllowHttp3);
4076 return NS_OK;
4077}
4078
4079NS_IMETHODIMPnsresult
4080HttpBaseChannel::GetAllowAltSvc(bool* aAllowAltSvc) {
4081 NS_ENSURE_ARG_POINTER(aAllowAltSvc)do { if ((__builtin_expect(!!(!(aAllowAltSvc)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowAltSvc" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4081); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4082
4083 *aAllowAltSvc = LoadAllowAltSvc();
4084 return NS_OK;
4085}
4086
4087NS_IMETHODIMPnsresult
4088HttpBaseChannel::SetAllowAltSvc(bool aAllowAltSvc) {
4089 StoreAllowAltSvc(aAllowAltSvc);
4090 return NS_OK;
4091}
4092
4093NS_IMETHODIMPnsresult
4094HttpBaseChannel::GetBeConservative(bool* aBeConservative) {
4095 NS_ENSURE_ARG_POINTER(aBeConservative)do { if ((__builtin_expect(!!(!(aBeConservative)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aBeConservative" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4095); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4096
4097 *aBeConservative = LoadBeConservative();
4098 return NS_OK;
4099}
4100
4101NS_IMETHODIMPnsresult
4102HttpBaseChannel::SetBeConservative(bool aBeConservative) {
4103 StoreBeConservative(aBeConservative);
4104 return NS_OK;
4105}
4106
4107bool HttpBaseChannel::BypassProxy() {
4108 return StaticPrefs::network_proxy_allow_bypass() && LoadBypassProxy();
4109}
4110
4111NS_IMETHODIMPnsresult
4112HttpBaseChannel::GetBypassProxy(bool* aBypassProxy) {
4113 NS_ENSURE_ARG_POINTER(aBypassProxy)do { if ((__builtin_expect(!!(!(aBypassProxy)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aBypassProxy" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4113); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4114
4115 *aBypassProxy = BypassProxy();
4116 return NS_OK;
4117}
4118
4119NS_IMETHODIMPnsresult
4120HttpBaseChannel::SetBypassProxy(bool aBypassProxy) {
4121 if (StaticPrefs::network_proxy_allow_bypass()) {
4122 StoreBypassProxy(aBypassProxy);
4123 } else {
4124 NS_WARNING("bypassProxy set but network.proxy.allow_bypass is disabled")NS_DebugBreak(NS_DEBUG_WARNING, "bypassProxy set but network.proxy.allow_bypass is disabled"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4124)
;
4125 return NS_ERROR_FAILURE;
4126 }
4127 return NS_OK;
4128}
4129
4130NS_IMETHODIMPnsresult
4131HttpBaseChannel::GetProxyDNSStrategy(
4132 nsIHttpChannelInternal::ProxyDNSStrategy* aStrategy) {
4133 NS_ENSURE_ARG_POINTER(aStrategy)do { if ((__builtin_expect(!!(!(aStrategy)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aStrategy" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4133
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4134 *aStrategy = nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN;
4135 return NS_OK;
4136}
4137
4138NS_IMETHODIMPnsresult
4139HttpBaseChannel::GetIsTRRServiceChannel(bool* aIsTRRServiceChannel) {
4140 NS_ENSURE_ARG_POINTER(aIsTRRServiceChannel)do { if ((__builtin_expect(!!(!(aIsTRRServiceChannel)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aIsTRRServiceChannel"
") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4140); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4141
4142 *aIsTRRServiceChannel = LoadIsTRRServiceChannel();
4143 return NS_OK;
4144}
4145
4146NS_IMETHODIMPnsresult
4147HttpBaseChannel::SetIsTRRServiceChannel(bool aIsTRRServiceChannel) {
4148 StoreIsTRRServiceChannel(aIsTRRServiceChannel);
4149 return NS_OK;
4150}
4151
4152NS_IMETHODIMPnsresult
4153HttpBaseChannel::GetIsResolvedByTRR(bool* aResolvedByTRR) {
4154 NS_ENSURE_ARG_POINTER(aResolvedByTRR)do { if ((__builtin_expect(!!(!(aResolvedByTRR)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResolvedByTRR" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4154); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4155 *aResolvedByTRR = LoadResolvedByTRR();
4156 return NS_OK;
4157}
4158
4159NS_IMETHODIMPnsresult
4160HttpBaseChannel::GetEffectiveTRRMode(nsIRequest::TRRMode* aEffectiveTRRMode) {
4161 *aEffectiveTRRMode = mEffectiveTRRMode;
4162 return NS_OK;
4163}
4164
4165NS_IMETHODIMPnsresult
4166HttpBaseChannel::GetTrrSkipReason(nsITRRSkipReason::value* aTrrSkipReason) {
4167 *aTrrSkipReason = mTRRSkipReason;
4168 return NS_OK;
4169}
4170
4171NS_IMETHODIMPnsresult
4172HttpBaseChannel::GetIsLoadedBySocketProcess(bool* aResult) {
4173 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4173
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4174 *aResult = LoadLoadedBySocketProcess();
4175 return NS_OK;
4176}
4177
4178NS_IMETHODIMPnsresult
4179HttpBaseChannel::GetTlsFlags(uint32_t* aTlsFlags) {
4180 NS_ENSURE_ARG_POINTER(aTlsFlags)do { if ((__builtin_expect(!!(!(aTlsFlags)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTlsFlags" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4180
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4181
4182 *aTlsFlags = mTlsFlags;
4183 return NS_OK;
4184}
4185
4186NS_IMETHODIMPnsresult
4187HttpBaseChannel::SetTlsFlags(uint32_t aTlsFlags) {
4188 mTlsFlags = aTlsFlags;
4189 return NS_OK;
4190}
4191
4192NS_IMETHODIMPnsresult
4193HttpBaseChannel::GetResponseTimeoutEnabled(bool* aEnable) {
4194 if (NS_WARN_IF(!aEnable)NS_warn_if_impl(!aEnable, "!aEnable", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4194)
) {
4195 return NS_ERROR_NULL_POINTER;
4196 }
4197 *aEnable = LoadResponseTimeoutEnabled();
4198 return NS_OK;
4199}
4200
4201NS_IMETHODIMPnsresult
4202HttpBaseChannel::SetResponseTimeoutEnabled(bool aEnable) {
4203 StoreResponseTimeoutEnabled(aEnable);
4204 return NS_OK;
4205}
4206
4207NS_IMETHODIMPnsresult
4208HttpBaseChannel::GetInitialRwin(uint32_t* aRwin) {
4209 if (NS_WARN_IF(!aRwin)NS_warn_if_impl(!aRwin, "!aRwin", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4209)
) {
4210 return NS_ERROR_NULL_POINTER;
4211 }
4212 *aRwin = mInitialRwin;
4213 return NS_OK;
4214}
4215
4216NS_IMETHODIMPnsresult
4217HttpBaseChannel::SetInitialRwin(uint32_t aRwin) {
4218 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4218); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4218, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4218); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4218
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 4218); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
4219 mInitialRwin = aRwin;
4220 return NS_OK;
4221}
4222
4223NS_IMETHODIMPnsresult
4224HttpBaseChannel::ForcePending(bool aForcePending) {
4225 StoreForcePending(aForcePending);
4226 return NS_OK;
4227}
4228
4229NS_IMETHODIMPnsresult
4230HttpBaseChannel::GetLastModifiedTime(PRTime* lastModifiedTime) {
4231 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
4232 uint32_t lastMod;
4233 nsresult rv = mResponseHead->GetLastModifiedValue(&lastMod);
4234 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4234); return rv; } } while (false)
;
4235 *lastModifiedTime = lastMod;
4236 return NS_OK;
4237}
4238
4239NS_IMETHODIMPnsresult
4240HttpBaseChannel::GetCorsIncludeCredentials(bool* aInclude) {
4241 *aInclude = LoadCorsIncludeCredentials();
4242 return NS_OK;
4243}
4244
4245NS_IMETHODIMPnsresult
4246HttpBaseChannel::SetCorsIncludeCredentials(bool aInclude) {
4247 StoreCorsIncludeCredentials(aInclude);
4248 return NS_OK;
4249}
4250
4251NS_IMETHODIMPnsresult
4252HttpBaseChannel::GetRequestMode(RequestMode* aMode) {
4253 *aMode = mRequestMode;
4254 return NS_OK;
4255}
4256
4257NS_IMETHODIMPnsresult
4258HttpBaseChannel::SetRequestMode(RequestMode aMode) {
4259 mRequestMode = aMode;
4260 return NS_OK;
4261}
4262
4263NS_IMETHODIMPnsresult
4264HttpBaseChannel::GetRedirectMode(uint32_t* aMode) {
4265 *aMode = mRedirectMode;
4266 return NS_OK;
4267}
4268
4269NS_IMETHODIMPnsresult
4270HttpBaseChannel::SetRedirectMode(uint32_t aMode) {
4271 mRedirectMode = aMode;
4272 return NS_OK;
4273}
4274
4275namespace {
4276
4277bool ContainsAllFlags(uint32_t aLoadFlags, uint32_t aMask) {
4278 return (aLoadFlags & aMask) == aMask;
4279}
4280
4281} // anonymous namespace
4282
4283NS_IMETHODIMPnsresult
4284HttpBaseChannel::GetFetchCacheMode(uint32_t* aFetchCacheMode) {
4285 NS_ENSURE_ARG_POINTER(aFetchCacheMode)do { if ((__builtin_expect(!!(!(aFetchCacheMode)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFetchCacheMode" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4285); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4286
4287 // Otherwise try to guess an appropriate cache mode from the load flags.
4288 if (ContainsAllFlags(mLoadFlags, INHIBIT_CACHING | LOAD_BYPASS_CACHE)) {
4289 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_STORE;
4290 } else if (ContainsAllFlags(mLoadFlags, LOAD_BYPASS_CACHE)) {
4291 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_RELOAD;
4292 } else if (ContainsAllFlags(mLoadFlags, VALIDATE_ALWAYS) ||
4293 LoadForceValidateCacheContent()) {
4294 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE;
4295 } else if (ContainsAllFlags(
4296 mLoadFlags,
4297 VALIDATE_NEVER | nsICachingChannel::LOAD_ONLY_FROM_CACHE)) {
4298 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED;
4299 } else if (ContainsAllFlags(mLoadFlags, VALIDATE_NEVER)) {
4300 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE;
4301 } else {
4302 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT;
4303 }
4304
4305 return NS_OK;
4306}
4307
4308namespace {
4309
4310void SetCacheFlags(Atomic<uint32_t, Relaxed>& aLoadFlags, uint32_t aFlags) {
4311 // First, clear any possible cache related flags
4312 uint32_t allPossibleFlags =
4313 nsIRequest::INHIBIT_CACHING | nsIRequest::LOAD_BYPASS_CACHE |
4314 nsIRequest::VALIDATE_ALWAYS | nsIRequest::LOAD_FROM_CACHE |
4315 nsICachingChannel::LOAD_ONLY_FROM_CACHE;
4316 aLoadFlags &= ~allPossibleFlags;
4317
4318 // Then set the new flags
4319 aLoadFlags |= aFlags;
4320}
4321
4322} // anonymous namespace
4323
4324NS_IMETHODIMPnsresult
4325HttpBaseChannel::SetFetchCacheMode(uint32_t aFetchCacheMode) {
4326 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4326); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4326, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4326); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4326
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 4326); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
4327
4328 // Now, set the load flags that implement each cache mode.
4329 switch (aFetchCacheMode) {
4330 case nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT:
4331 // The "default" mode means to use the http cache normally and
4332 // respect any http cache-control headers. We effectively want
4333 // to clear our cache related load flags.
4334 SetCacheFlags(mLoadFlags, 0);
4335 break;
4336 case nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_STORE:
4337 // no-store means don't consult the cache on the way to the network, and
4338 // don't store the response in the cache even if it's cacheable.
4339 SetCacheFlags(mLoadFlags, INHIBIT_CACHING | LOAD_BYPASS_CACHE);
4340 break;
4341 case nsIHttpChannelInternal::FETCH_CACHE_MODE_RELOAD:
4342 // reload means don't consult the cache on the way to the network, but
4343 // do store the response in the cache if possible.
4344 SetCacheFlags(mLoadFlags, LOAD_BYPASS_CACHE);
4345 break;
4346 case nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE:
4347 // no-cache means always validate what's in the cache.
4348 SetCacheFlags(mLoadFlags, VALIDATE_ALWAYS);
4349 break;
4350 case nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE:
4351 // force-cache means don't validate unless if the response would vary.
4352 SetCacheFlags(mLoadFlags, VALIDATE_NEVER);
4353 break;
4354 case nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED:
4355 // only-if-cached means only from cache, no network, no validation,
4356 // generate a network error if the document was't in the cache. The
4357 // privacy implications of these flags (making it fast/easy to check if
4358 // the user has things in their cache without any network traffic side
4359 // effects) are addressed in the Request constructor which
4360 // enforces/requires same-origin request mode.
4361 SetCacheFlags(mLoadFlags,
4362 VALIDATE_NEVER | nsICachingChannel::LOAD_ONLY_FROM_CACHE);
4363 break;
4364 }
4365
4366#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
4367 uint32_t finalMode = 0;
4368 MOZ_ALWAYS_SUCCEEDS(GetFetchCacheMode(&finalMode))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(GetFetchCacheMode(&finalMode))), 1)))), 1))) { } else { do
{ do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(GetFetchCacheMode(&finalMode))"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4368
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(GetFetchCacheMode(&finalMode))"
")"); do { MOZ_CrashSequence(__null, 4368); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
4369 MOZ_DIAGNOSTIC_ASSERT(finalMode == aFetchCacheMode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(finalMode == aFetchCacheMode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(finalMode == aFetchCacheMode
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"finalMode == aFetchCacheMode", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4369); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "finalMode == aFetchCacheMode"
")"); do { MOZ_CrashSequence(__null, 4369); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4370#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED
4371
4372 return NS_OK;
4373}
4374
4375//-----------------------------------------------------------------------------
4376// HttpBaseChannel::nsISupportsPriority
4377//-----------------------------------------------------------------------------
4378
4379NS_IMETHODIMPnsresult
4380HttpBaseChannel::GetPriority(int32_t* value) {
4381 *value = mPriority;
4382 return NS_OK;
4383}
4384
4385NS_IMETHODIMPnsresult
4386HttpBaseChannel::AdjustPriority(int32_t delta) {
4387 return SetPriority(mPriority + delta);
4388}
4389
4390//-----------------------------------------------------------------------------
4391// HttpBaseChannel::nsIResumableChannel
4392//-----------------------------------------------------------------------------
4393
4394NS_IMETHODIMPnsresult
4395HttpBaseChannel::GetEntityID(nsACString& aEntityID) {
4396 // Don't return an entity ID for Non-GET requests which require
4397 // additional data
4398 if (!mRequestHead.IsGet()) {
4399 return NS_ERROR_NOT_RESUMABLE;
4400 }
4401
4402 uint64_t size = UINT64_MAX(18446744073709551615UL);
4403 nsAutoCString etag, lastmod;
4404 if (mResponseHead) {
4405 // Don't return an entity if the server sent the following header:
4406 // Accept-Ranges: none
4407 // Not sending the Accept-Ranges header means we can still try
4408 // sending range requests.
4409 nsAutoCString acceptRanges;
4410 (void)mResponseHead->GetHeader(nsHttp::Accept_Ranges, acceptRanges);
4411 if (!acceptRanges.IsEmpty() &&
4412 !nsHttp::FindToken(acceptRanges.get(), "bytes",
4413 HTTP_HEADER_VALUE_SEPS" \t" ",")) {
4414 return NS_ERROR_NOT_RESUMABLE;
4415 }
4416
4417 size = mResponseHead->TotalEntitySize();
4418 (void)mResponseHead->GetHeader(nsHttp::Last_Modified, lastmod);
4419 (void)mResponseHead->GetHeader(nsHttp::ETag, etag);
4420 }
4421 nsCString entityID;
4422 NS_EscapeURL(etag.BeginReading(), etag.Length(),
4423 esc_AlwaysCopy | esc_FileBaseName | esc_Forced, entityID);
4424 entityID.Append('/');
4425 entityID.AppendInt(int64_t(size));
4426 entityID.Append('/');
4427 entityID.Append(lastmod);
4428 // NOTE: Appending lastmod as the last part avoids having to escape it
4429
4430 aEntityID = std::move(entityID);
4431
4432 return NS_OK;
4433}
4434
4435//-----------------------------------------------------------------------------
4436// HttpBaseChannel::nsIConsoleReportCollector
4437//-----------------------------------------------------------------------------
4438
4439void HttpBaseChannel::AddConsoleReport(
4440 uint32_t aErrorFlags, const nsACString& aCategory,
4441 PropertiesFile aPropertiesFile, const nsACString& aSourceFileURI,
4442 uint32_t aLineNumber, uint32_t aColumnNumber,
4443 const nsACString& aMessageName, const nsTArray<nsString>& aStringParams) {
4444 mReportCollector->AddConsoleReport(aErrorFlags, aCategory, aPropertiesFile,
4445 aSourceFileURI, aLineNumber, aColumnNumber,
4446 aMessageName, aStringParams);
4447
4448 // If this channel is already part of a loadGroup, we can flush this console
4449 // report immediately.
4450 HttpBaseChannel::MaybeFlushConsoleReports();
4451}
4452
4453void HttpBaseChannel::FlushReportsToConsole(uint64_t aInnerWindowID,
4454 ReportAction aAction) {
4455 mReportCollector->FlushReportsToConsole(aInnerWindowID, aAction);
4456}
4457
4458void HttpBaseChannel::FlushReportsToConsoleForServiceWorkerScope(
4459 const nsACString& aScope, ReportAction aAction) {
4460 mReportCollector->FlushReportsToConsoleForServiceWorkerScope(aScope, aAction);
4461}
4462
4463void HttpBaseChannel::FlushConsoleReports(dom::Document* aDocument,
4464 ReportAction aAction) {
4465 mReportCollector->FlushConsoleReports(aDocument, aAction);
4466}
4467
4468void HttpBaseChannel::FlushConsoleReports(nsILoadGroup* aLoadGroup,
4469 ReportAction aAction) {
4470 mReportCollector->FlushConsoleReports(aLoadGroup, aAction);
4471}
4472
4473void HttpBaseChannel::FlushConsoleReports(
4474 nsIConsoleReportCollector* aCollector) {
4475 mReportCollector->FlushConsoleReports(aCollector);
4476}
4477
4478void HttpBaseChannel::StealConsoleReports(
4479 nsTArray<net::ConsoleReportCollected>& aReports) {
4480 mReportCollector->StealConsoleReports(aReports);
4481}
4482
4483void HttpBaseChannel::ClearConsoleReports() {
4484 mReportCollector->ClearConsoleReports();
4485}
4486
4487bool HttpBaseChannel::IsNavigation() {
4488 return LoadForceMainDocumentChannel() || (mLoadFlags & LOAD_DOCUMENT_URI);
4489}
4490
4491nsresult HttpBaseChannel::GetAltDataBindingOrigin(nsACString& aOrigin) {
4492 aOrigin.Truncate();
4493 if (!mLoadInfo) {
4494 return NS_ERROR_FAILURE;
4495 }
4496
4497 nsCOMPtr<nsIPrincipal> principal = mLoadInfo->GetLoadingPrincipal();
4498 if (!principal) {
4499 principal = mLoadInfo->TriggeringPrincipal();
4500 }
4501 if (!principal) {
4502 return NS_ERROR_FAILURE;
4503 }
4504 return principal->GetOrigin(aOrigin);
4505}
4506
4507bool HttpBaseChannel::BypassServiceWorker() const {
4508 return mLoadFlags & LOAD_BYPASS_SERVICE_WORKER;
4509}
4510
4511bool HttpBaseChannel::ShouldIntercept(nsIURI* aURI) {
4512 nsCOMPtr<nsINetworkInterceptController> controller;
4513 GetCallback(controller);
4514 bool shouldIntercept = false;
4515
4516 if (!StaticPrefs::dom_serviceWorkers_enabled()) {
4517 return false;
4518 }
4519
4520 // We should never intercept internal redirects. The ServiceWorker code
4521 // can trigger interntal redirects as the result of a FetchEvent. If
4522 // we re-intercept then an infinite loop can occur.
4523 //
4524 // Its also important that we do not set the LOAD_BYPASS_SERVICE_WORKER
4525 // flag because an internal redirect occurs. Its possible that another
4526 // interception should occur after the internal redirect. For example,
4527 // if the ServiceWorker chooses not to call respondWith() the channel
4528 // will be reset with an internal redirect. If the request is a navigation
4529 // and the network then triggers a redirect its possible the new URL
4530 // should be intercepted again.
4531 //
4532 // Note, HSTS upgrade redirects are often treated the same as internal
4533 // redirects. In this case, however, we intentionally allow interception
4534 // of HSTS upgrade redirects. This matches the expected spec behavior and
4535 // does not run the risk of infinite loops as described above.
4536 bool internalRedirect =
4537 mLastRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL;
4538
4539 if (controller && mLoadInfo && !BypassServiceWorker() && !internalRedirect) {
4540 nsresult rv = controller->ShouldPrepareForIntercept(
4541 aURI ? aURI : mURI.get(), this, &shouldIntercept);
4542 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4543 return false;
4544 }
4545 }
4546 return shouldIntercept;
4547}
4548
4549void HttpBaseChannel::AddAsNonTailRequest() {
4550 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4550
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 4550); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4551
4552 if (EnsureRequestContext()) {
4553 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::AddAsNonTailRequest this=%p, rc=%p, already added=%d"
, this, mRequestContext.get(), (bool)LoadAddedAsNonTailRequest
()); } } while (0)
4554 "HttpBaseChannel::AddAsNonTailRequest this=%p, rc=%p, already added=%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
, "HttpBaseChannel::AddAsNonTailRequest this=%p, rc=%p, already added=%d"
, this, mRequestContext.get(), (bool)LoadAddedAsNonTailRequest
()); } } while (0)
4555 this, mRequestContext.get(), (bool)LoadAddedAsNonTailRequest()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::AddAsNonTailRequest this=%p, rc=%p, already added=%d"
, this, mRequestContext.get(), (bool)LoadAddedAsNonTailRequest
()); } } while (0)
;
4556
4557 if (!LoadAddedAsNonTailRequest()) {
4558 mRequestContext->AddNonTailRequest();
4559 StoreAddedAsNonTailRequest(true);
4560 }
4561 }
4562}
4563
4564void HttpBaseChannel::RemoveAsNonTailRequest() {
4565 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4565
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 4565); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4566
4567 if (mRequestContext) {
4568 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::RemoveAsNonTailRequest this=%p, rc=%p, already "
"added=%d", this, mRequestContext.get(), (bool)LoadAddedAsNonTailRequest
()); } } while (0)
4569 ("HttpBaseChannel::RemoveAsNonTailRequest this=%p, rc=%p, already "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::RemoveAsNonTailRequest this=%p, rc=%p, already "
"added=%d", this, mRequestContext.get(), (bool)LoadAddedAsNonTailRequest
()); } } while (0)
4570 "added=%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
, "HttpBaseChannel::RemoveAsNonTailRequest this=%p, rc=%p, already "
"added=%d", this, mRequestContext.get(), (bool)LoadAddedAsNonTailRequest
()); } } while (0)
4571 this, mRequestContext.get(), (bool)LoadAddedAsNonTailRequest()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::RemoveAsNonTailRequest this=%p, rc=%p, already "
"added=%d", this, mRequestContext.get(), (bool)LoadAddedAsNonTailRequest
()); } } while (0)
;
4572
4573 if (LoadAddedAsNonTailRequest()) {
4574 mRequestContext->RemoveNonTailRequest();
4575 StoreAddedAsNonTailRequest(false);
4576 }
4577 }
4578}
4579
4580#ifdef DEBUG1
4581void HttpBaseChannel::AssertPrivateBrowsingId() {
4582 nsCOMPtr<nsILoadContext> loadContext;
4583 NS_QueryNotificationCallbacks(this, loadContext);
4584
4585 if (!loadContext) {
4586 return;
4587 }
4588
4589 // We skip testing of favicon loading here since it could be triggered by XUL
4590 // image which uses SystemPrincipal. The SystemPrincpal doesn't have
4591 // mPrivateBrowsingId.
4592 if (mLoadInfo->GetLoadingPrincipal() &&
4593 mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal() &&
4594 mLoadInfo->InternalContentPolicyType() ==
4595 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
4596 return;
4597 }
4598
4599 OriginAttributes docShellAttrs;
4600 loadContext->GetOriginAttributes(docShellAttrs);
4601 MOZ_ASSERT(mLoadInfo->GetOriginAttributes().mPrivateBrowsingId ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetOriginAttributes().mPrivateBrowsingId
== docShellAttrs.mPrivateBrowsingId)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo->GetOriginAttributes
().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
" (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
") (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")"); do { MOZ_CrashSequence(__null, 4604); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
4602 docShellAttrs.mPrivateBrowsingId,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetOriginAttributes().mPrivateBrowsingId
== docShellAttrs.mPrivateBrowsingId)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo->GetOriginAttributes
().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
" (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
") (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")"); do { MOZ_CrashSequence(__null, 4604); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
4603 "PrivateBrowsingId values are not the same between LoadInfo and "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetOriginAttributes().mPrivateBrowsingId
== docShellAttrs.mPrivateBrowsingId)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo->GetOriginAttributes
().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
" (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
") (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")"); do { MOZ_CrashSequence(__null, 4604); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
4604 "LoadContext.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetOriginAttributes().mPrivateBrowsingId
== docShellAttrs.mPrivateBrowsingId)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo->GetOriginAttributes
().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
" (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
") (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")"); do { MOZ_CrashSequence(__null, 4604); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
4605}
4606#endif
4607
4608already_AddRefed<nsILoadInfo> HttpBaseChannel::CloneLoadInfoForRedirect(
4609 nsIURI* aNewURI, uint32_t aRedirectFlags) {
4610 // make a copy of the loadinfo, append to the redirectchain
4611 // this will be set on the newly created channel for the redirect target.
4612 nsCOMPtr<nsILoadInfo> newLoadInfo =
4613 static_cast<mozilla::net::LoadInfo*>(mLoadInfo.get())->Clone();
4614
4615 ExtContentPolicyType contentPolicyType =
4616 mLoadInfo->GetExternalContentPolicyType();
4617 if (contentPolicyType == ExtContentPolicy::TYPE_DOCUMENT ||
4618 contentPolicyType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
4619 // Reset PrincipalToInherit to a null principal. We'll credit the the
4620 // redirecting resource's result principal as the new principal's precursor.
4621 // This means that a data: URI will end up loading in a process based on the
4622 // redirected-from URI.
4623 nsCOMPtr<nsIPrincipal> redirectPrincipal;
4624 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
4625 this, getter_AddRefs(redirectPrincipal));
4626 nsCOMPtr<nsIPrincipal> nullPrincipalToInherit =
4627 NullPrincipal::CreateWithInheritedAttributes(redirectPrincipal);
4628 newLoadInfo->SetTrustedPrincipalToInherit(nullPrincipalToInherit);
4629 }
4630
4631 bool isTopLevelDoc = newLoadInfo->GetExternalContentPolicyType() ==
4632 ExtContentPolicy::TYPE_DOCUMENT;
4633
4634 if (isTopLevelDoc) {
4635 // re-compute the origin attributes of the loadInfo if it's top-level load.
4636 nsCOMPtr<nsILoadContext> loadContext;
4637 NS_QueryNotificationCallbacks(this, loadContext);
4638 OriginAttributes attrs;
4639 if (loadContext) {
4640 loadContext->GetOriginAttributes(attrs);
4641 }
4642
4643 OriginAttributes channelAttrs = newLoadInfo->GetOriginAttributes();
4644
4645 // Preserve the container from the channel attributes, as it could
4646 // legitimately differ from the loadContext.
4647 attrs.mUserContextId = channelAttrs.mUserContextId;
4648
4649 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId"
" (" "docshell and necko should have the same privateBrowsingId attribute."
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId"
") (" "docshell and necko should have the same privateBrowsingId attribute."
")"); do { MOZ_CrashSequence(__null, 4651); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4650 attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId"
" (" "docshell and necko should have the same privateBrowsingId attribute."
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId"
") (" "docshell and necko should have the same privateBrowsingId attribute."
")"); do { MOZ_CrashSequence(__null, 4651); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4651 "docshell and necko should have the same privateBrowsingId attribute.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId"
" (" "docshell and necko should have the same privateBrowsingId attribute."
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId"
") (" "docshell and necko should have the same privateBrowsingId attribute."
")"); do { MOZ_CrashSequence(__null, 4651); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4652 MOZ_ASSERT(attrs.mGeckoViewSessionContextId ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
" (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
") (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")"); do { MOZ_CrashSequence(__null, 4655); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4653 channelAttrs.mGeckoViewSessionContextId,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
" (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
") (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")"); do { MOZ_CrashSequence(__null, 4655); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4654 "docshell and necko should have the same "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
" (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
") (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")"); do { MOZ_CrashSequence(__null, 4655); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4655 "geckoViewSessionContextId attribute")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
" (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
") (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")"); do { MOZ_CrashSequence(__null, 4655); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4656
4657 attrs.SetFirstPartyDomain(true, aNewURI);
4658
4659 newLoadInfo->SetOriginAttributes(attrs);
4660
4661 // re-compute the upgrade insecure requests bit for document navigations
4662 // since it should only apply to same-origin navigations (redirects).
4663 // we only do this if the CSP of the triggering element (the cspToInherit)
4664 // uses 'upgrade-insecure-requests', otherwise UIR does not apply.
4665 nsCOMPtr<nsIPolicyContainer> policyContainer =
4666 newLoadInfo->GetPolicyContainerToInherit();
4667 nsCOMPtr<nsIContentSecurityPolicy> csp =
4668 PolicyContainer::GetCSP(policyContainer);
4669 if (csp) {
4670 bool upgradeInsecureRequests = false;
4671 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
4672 if (upgradeInsecureRequests) {
4673 nsCOMPtr<nsIPrincipal> resultPrincipal =
4674 BasePrincipal::CreateContentPrincipal(
4675 aNewURI, newLoadInfo->GetOriginAttributes());
4676 bool isConsideredSameOriginforUIR =
4677 nsContentSecurityUtils::IsConsideredSameOriginForUIR(
4678 newLoadInfo->TriggeringPrincipal(), resultPrincipal);
4679 static_cast<mozilla::net::LoadInfo*>(newLoadInfo.get())
4680 ->SetUpgradeInsecureRequests(isConsideredSameOriginforUIR);
4681 }
4682 }
4683 }
4684
4685 // Clone a new cookieJarSettings from the old one for the new channel.
4686 // Otherwise, updating the new cookieJarSettings will affect the old one.
4687 nsCOMPtr<nsICookieJarSettings> oldCookieJarSettings;
4688 mLoadInfo->GetCookieJarSettings(getter_AddRefs(oldCookieJarSettings));
4689
4690 RefPtr<CookieJarSettings> newCookieJarSettings;
4691 newCookieJarSettings = CookieJarSettings::Cast(oldCookieJarSettings)->Clone();
4692
4693 newLoadInfo->SetCookieJarSettings(newCookieJarSettings);
4694
4695 // Clear the isThirdPartyContextToTopWindow flag for the new channel so that
4696 // it will be computed again when the new channel is opened.
4697 static_cast<net::LoadInfo*>(newLoadInfo.get())
4698 ->ClearIsThirdPartyContextToTopWindow();
4699
4700 // Leave empty, we want a 'clean ground' when creating the new channel.
4701 // This will be ensured to be either set by the protocol handler or set
4702 // to the redirect target URI properly after the channel creation.
4703 newLoadInfo->SetResultPrincipalURI(nullptr);
4704
4705 bool isInternalRedirect =
4706 (aRedirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
4707 nsIChannelEventSink::REDIRECT_STS_UPGRADE));
4708
4709 // Reset our sandboxed null principal ID when cloning loadInfo for an
4710 // externally visible redirect.
4711 if (!isInternalRedirect) {
4712 // If we've redirected from http to something that isn't, clear
4713 // the "external" flag, as loads that now go to other apps should be
4714 // allowed to go ahead and not trip infinite-loop protection
4715 // (see bug 1717314 for context).
4716 if (!net::SchemeIsHttpOrHttps(aNewURI)) {
4717 newLoadInfo->SetLoadTriggeredFromExternal(false);
4718 }
4719 newLoadInfo->ResetSandboxedNullPrincipalID();
4720
4721 if (isTopLevelDoc) {
4722 // Reset HTTPS-first and -only status on http redirect. To not
4723 // unexpectedly downgrade requests that weren't upgraded via HTTPS-First
4724 // (Bug 1904238).
4725 (void)newLoadInfo->SetHttpsOnlyStatus(
4726 nsILoadInfo::HTTPS_ONLY_UNINITIALIZED);
4727
4728 // Reset schemeless status flag to prevent schemeless HTTPS-First from
4729 // repeatedly trying to upgrade loads that get downgraded again from the
4730 // server by a redirect (Bug 1937386).
4731 (void)newLoadInfo->SetSchemelessInput(
4732 nsILoadInfo::SchemelessInputTypeUnset);
4733 }
4734 }
4735
4736 newLoadInfo->AppendRedirectHistoryEntry(this, isInternalRedirect);
4737
4738 return newLoadInfo.forget();
4739}
4740
4741//-----------------------------------------------------------------------------
4742// nsHttpChannel::nsITraceableChannel
4743//-----------------------------------------------------------------------------
4744
4745NS_IMETHODIMPnsresult
4746HttpBaseChannel::SetNewListener(nsIStreamListener* aListener,
4747 bool aMustApplyContentConversion,
4748 nsIStreamListener** _retval) {
4749 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetNewListener [this=%p, mListener=%p, newListener=%p]"
, this, mListener.get(), aListener); } } while (0)
4750 "HttpBaseChannel::SetNewListener [this=%p, mListener=%p, newListener=%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
, "HttpBaseChannel::SetNewListener [this=%p, mListener=%p, newListener=%p]"
, this, mListener.get(), aListener); } } while (0)
4751 this, mListener.get(), aListener))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetNewListener [this=%p, mListener=%p, newListener=%p]"
, this, mListener.get(), aListener); } } while (0)
;
4752
4753 if (!LoadTracingEnabled()) return NS_ERROR_FAILURE;
4754
4755 NS_ENSURE_STATE(mListener)do { if ((__builtin_expect(!!(!(mListener)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mListener" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4755
); return NS_ERROR_UNEXPECTED; } } while (false)
;
4756 NS_ENSURE_ARG_POINTER(aListener)do { if ((__builtin_expect(!!(!(aListener)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aListener" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 4756
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4757
4758 nsCOMPtr<nsIStreamListener> wrapper = new nsStreamListenerWrapper(mListener);
4759
4760 wrapper.forget(_retval);
4761 mListener = aListener;
4762 if (aMustApplyContentConversion) {
4763 StoreListenerRequiresContentConversion(true);
4764 }
4765 return NS_OK;
4766}
4767
4768//-----------------------------------------------------------------------------
4769// HttpBaseChannel helpers
4770//-----------------------------------------------------------------------------
4771
4772void HttpBaseChannel::ReleaseListeners() {
4773 MOZ_ASSERT(mCurrentThread->IsOnCurrentThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCurrentThread->IsOnCurrentThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mCurrentThread->IsOnCurrentThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mCurrentThread->IsOnCurrentThread()"
" (" "Should only be called on the current thread" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentThread->IsOnCurrentThread()"
") (" "Should only be called on the current thread" ")"); do
{ MOZ_CrashSequence(__null, 4774); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4774 "Should only be called on the current thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCurrentThread->IsOnCurrentThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mCurrentThread->IsOnCurrentThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mCurrentThread->IsOnCurrentThread()"
" (" "Should only be called on the current thread" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentThread->IsOnCurrentThread()"
") (" "Should only be called on the current thread" ")"); do
{ MOZ_CrashSequence(__null, 4774); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4775
4776 mListener = nullptr;
4777 mCallbacks = nullptr;
4778 mProgressSink = nullptr;
4779 mCompressListener = nullptr;
4780 mORB = nullptr;
4781}
4782
4783void HttpBaseChannel::DoNotifyListener() {
4784 LOG(("HttpBaseChannel::DoNotifyListener 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
, "HttpBaseChannel::DoNotifyListener this=%p", this); } } while
(0)
;
4785
4786 // In case nsHttpChannel::OnStartRequest wasn't called (e.g. due to flag
4787 // LOAD_ONLY_IF_MODIFIED) we want to set AfterOnStartRequestBegun to true
4788 // before notifying listener.
4789 if (!LoadAfterOnStartRequestBegun()) {
4790 StoreAfterOnStartRequestBegun(true);
4791 }
4792
4793 if (mListener && !LoadOnStartRequestCalled()) {
4794 nsCOMPtr<nsIStreamListener> listener = mListener;
4795 StoreOnStartRequestCalled(true);
4796 listener->OnStartRequest(this);
4797 }
4798 StoreOnStartRequestCalled(true);
4799
4800 // Make sure IsPending is set to false. At this moment we are done from
4801 // the point of view of our consumer and we have to report our self
4802 // as not-pending.
4803 StoreIsPending(false);
4804
4805 // notify "http-on-before-stop-request" observers
4806 gHttpHandler->OnBeforeStopRequest(this);
4807
4808 if (mListener && !LoadOnStopRequestCalled()) {
4809 nsCOMPtr<nsIStreamListener> listener = mListener;
4810 StoreOnStopRequestCalled(true);
4811 listener->OnStopRequest(this, mStatus);
4812 }
4813 StoreOnStopRequestCalled(true);
4814
4815 // notify "http-on-stop-request" observers
4816 gHttpHandler->OnStopRequest(this);
4817
4818 // This channel has finished its job, potentially release any tail-blocked
4819 // requests with this.
4820 RemoveAsNonTailRequest();
4821
4822 // We have to make sure to drop the references to listeners and callbacks
4823 // no longer needed.
4824 ReleaseListeners();
4825
4826 DoNotifyListenerCleanup();
4827
4828 // If this is a navigation, then we must let the docshell flush the reports
4829 // to the console later. The LoadDocument() is pointing at the detached
4830 // document that started the navigation. We want to show the reports on the
4831 // new document. Otherwise the console is wiped and the user never sees
4832 // the information.
4833 if (!IsNavigation()) {
4834 if (mLoadGroup) {
4835 FlushConsoleReports(mLoadGroup);
4836 } else {
4837 RefPtr<dom::Document> doc;
4838 mLoadInfo->GetLoadingDocument(getter_AddRefs(doc));
4839 FlushConsoleReports(doc);
4840 }
4841 }
4842}
4843
4844void HttpBaseChannel::AddCookiesToRequest() {
4845 if (mLoadFlags & LOAD_ANONYMOUS) {
4846 return;
4847 }
4848
4849 bool useCookieService = (XRE_IsParentProcess());
4850 nsAutoCString cookie;
4851 if (useCookieService) {
4852 nsICookieService* cs = gHttpHandler->GetCookieService();
4853 if (cs) {
4854 cs->GetCookieStringFromHttp(mURI, this, cookie);
4855 }
4856
4857 if (cookie.IsEmpty()) {
4858 cookie = mUserSetCookieHeader;
4859 } else if (!mUserSetCookieHeader.IsEmpty()) {
4860 cookie.AppendLiteral("; ");
4861 cookie.Append(mUserSetCookieHeader);
4862 }
4863 } else {
4864 cookie = mUserSetCookieHeader;
4865 }
4866
4867 // If we are in the child process, we want the parent seeing any
4868 // cookie headers that might have been set by SetRequestHeader()
4869 SetRequestHeader(nsHttp::Cookie.val(), cookie, false);
4870}
4871
4872/* static */
4873void HttpBaseChannel::PropagateReferenceIfNeeded(
4874 nsIURI* aURI, nsCOMPtr<nsIURI>& aRedirectURI) {
4875 bool hasRef = false;
4876 nsresult rv = aRedirectURI->GetHasRef(&hasRef);
4877 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !hasRef) {
4878 nsAutoCString ref;
4879 aURI->GetRef(ref);
4880 if (!ref.IsEmpty()) {
4881 // NOTE: SetRef will fail if mRedirectURI is immutable
4882 // (e.g. an about: URI)... Oh well.
4883 (void)NS_MutateURI(aRedirectURI).SetRef(ref).Finalize(aRedirectURI);
4884 }
4885 }
4886}
4887
4888bool HttpBaseChannel::ShouldRewriteRedirectToGET(
4889 uint32_t httpStatus, nsHttpRequestHead::ParsedMethodType method) {
4890 // for 301 and 302, only rewrite POST
4891 if (httpStatus == 301 || httpStatus == 302) {
4892 return method == nsHttpRequestHead::kMethod_Post;
4893 }
4894
4895 // rewrite for 303 unless it was HEAD
4896 if (httpStatus == 303) return method != nsHttpRequestHead::kMethod_Head;
4897
4898 // otherwise, such as for 307, do not rewrite
4899 return false;
4900}
4901
4902NS_IMETHODIMPnsresult
4903HttpBaseChannel::ShouldStripRequestBodyHeader(const nsACString& aMethod,
4904 bool* aResult) {
4905 *aResult = false;
4906 uint32_t httpStatus = 0;
4907 if (NS_FAILED(GetResponseStatus(&httpStatus))((bool)(__builtin_expect(!!(NS_FAILED_impl(GetResponseStatus(
&httpStatus))), 0)))
) {
4908 return NS_OK;
4909 }
4910
4911 nsAutoCString method(aMethod);
4912 nsHttpRequestHead::ParsedMethodType parsedMethod;
4913 nsHttpRequestHead::ParseMethod(method, parsedMethod);
4914 // Fetch 4.4.11, which is slightly different than the perserved method
4915 // algrorithm: strip request-body-header for GET->GET redirection for 303.
4916 *aResult =
4917 ShouldRewriteRedirectToGET(httpStatus, parsedMethod) &&
4918 !(httpStatus == 303 && parsedMethod == nsHttpRequestHead::kMethod_Get);
4919
4920 return NS_OK;
4921}
4922
4923HttpBaseChannel::ReplacementChannelConfig
4924HttpBaseChannel::CloneReplacementChannelConfig(bool aPreserveMethod,
4925 uint32_t aRedirectFlags,
4926 ReplacementReason aReason) {
4927 ReplacementChannelConfig config;
4928 config.redirectFlags = aRedirectFlags;
4929 config.classOfService = mClassOfService;
4930
4931 if (mPrivateBrowsingOverriden) {
4932 config.privateBrowsing = Some(mPrivateBrowsing);
4933 }
4934
4935 if (mReferrerInfo) {
4936 // When cloning for a document channel replacement (parent process
4937 // copying values for a new content process channel), this happens after
4938 // OnStartRequest so we have the headers for the response available.
4939 // We don't want to apply them to the referrer for the channel though,
4940 // since that is the referrer for the current document, and the header
4941 // should only apply to navigations from the current document.
4942 if (aReason == ReplacementReason::DocumentChannel) {
4943 config.referrerInfo = mReferrerInfo;
4944 } else {
4945 dom::ReferrerPolicy referrerPolicy = dom::ReferrerPolicy::_empty;
4946 nsAutoCString tRPHeaderCValue;
4947 (void)GetResponseHeader("referrer-policy"_ns, tRPHeaderCValue);
4948 NS_ConvertUTF8toUTF16 tRPHeaderValue(tRPHeaderCValue);
4949
4950 if (!tRPHeaderValue.IsEmpty()) {
4951 referrerPolicy =
4952 dom::ReferrerInfo::ReferrerPolicyFromHeaderString(tRPHeaderValue);
4953 }
4954
4955 // In case we are here because an upgrade happened through mixed content
4956 // upgrading, CSP upgrade-insecure-requests, HTTPS-Only or HTTPS-First, we
4957 // have to recalculate the referrer based on the original referrer to
4958 // account for the different scheme. This does NOT apply to HSTS.
4959 // See Bug 1857894 and order of https://fetch.spec.whatwg.org/#main-fetch.
4960 // Otherwise, if we have a new referrer policy, we want to recalculate the
4961 // referrer based on the old computed referrer (Bug 1678545).
4962 bool wasNonHSTSUpgrade =
4963 (aRedirectFlags & nsIChannelEventSink::REDIRECT_STS_UPGRADE) &&
4964 (!mLoadInfo->GetHstsStatus());
4965 if (wasNonHSTSUpgrade) {
4966 nsCOMPtr<nsIURI> referrer = mReferrerInfo->GetOriginalReferrer();
4967 config.referrerInfo =
4968 new dom::ReferrerInfo(referrer, mReferrerInfo->ReferrerPolicy(),
4969 mReferrerInfo->GetSendReferrer());
4970 } else if (referrerPolicy != dom::ReferrerPolicy::_empty) {
4971 nsCOMPtr<nsIURI> referrer = mReferrerInfo->GetComputedReferrer();
4972 config.referrerInfo = new dom::ReferrerInfo(
4973 referrer, referrerPolicy, mReferrerInfo->GetSendReferrer());
4974 } else {
4975 config.referrerInfo = mReferrerInfo;
4976 }
4977 }
4978 }
4979
4980 nsCOMPtr<nsITimedChannel> oldTimedChannel(
4981 do_QueryInterface(static_cast<nsIHttpChannel*>(this)));
4982 if (oldTimedChannel) {
4983 config.timedChannelInfo = Some(dom::TimedChannelInfo());
4984 config.timedChannelInfo->redirectCount() = mRedirectCount;
4985 config.timedChannelInfo->internalRedirectCount() = mInternalRedirectCount;
4986 config.timedChannelInfo->asyncOpen() = mAsyncOpenTime;
4987 config.timedChannelInfo->channelCreation() = mChannelCreationTimestamp;
4988 config.timedChannelInfo->redirectStart() = mRedirectStartTimeStamp;
4989 config.timedChannelInfo->redirectEnd() = mRedirectEndTimeStamp;
4990 config.timedChannelInfo->initiatorType() = mInitiatorType;
4991 config.timedChannelInfo->allRedirectsSameOrigin() =
4992 LoadAllRedirectsSameOrigin();
4993 config.timedChannelInfo->allRedirectsSameOriginIgnoringInternal() =
4994 LoadAllRedirectsSameOriginIgnoringInternal();
4995 config.timedChannelInfo->allRedirectsPassTimingAllowCheck() =
4996 LoadAllRedirectsPassTimingAllowCheck();
4997 // Execute the timing allow check to determine whether
4998 // to report the redirect timing info
4999 nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
5000 // TYPE_DOCUMENT loads don't have a loadingPrincipal, so we can't set
5001 // AllRedirectsPassTimingAllowCheck on them.
5002 if (loadInfo->GetExternalContentPolicyType() !=
5003 ExtContentPolicy::TYPE_DOCUMENT) {
5004 nsCOMPtr<nsIPrincipal> principal = loadInfo->GetLoadingPrincipal();
5005 config.timedChannelInfo->timingAllowCheckForPrincipal() =
5006 Some(oldTimedChannel->TimingAllowCheck(principal));
5007 }
5008
5009 config.timedChannelInfo->allRedirectsPassTimingAllowCheck() =
5010 LoadAllRedirectsPassTimingAllowCheck();
5011 config.timedChannelInfo->launchServiceWorkerStart() =
5012 mLaunchServiceWorkerStart;
5013 config.timedChannelInfo->launchServiceWorkerEnd() = mLaunchServiceWorkerEnd;
5014 config.timedChannelInfo->dispatchFetchEventStart() =
5015 mDispatchFetchEventStart;
5016 config.timedChannelInfo->dispatchFetchEventEnd() = mDispatchFetchEventEnd;
5017 config.timedChannelInfo->handleFetchEventStart() = mHandleFetchEventStart;
5018 config.timedChannelInfo->handleFetchEventEnd() = mHandleFetchEventEnd;
5019 config.timedChannelInfo->responseStart() =
5020 mTransactionTimings.responseStart;
5021 config.timedChannelInfo->responseEnd() = mTransactionTimings.responseEnd;
5022 }
5023
5024 if (aPreserveMethod) {
5025 // since preserveMethod is true, we need to ensure that the appropriate
5026 // request method gets set on the channel, regardless of whether or not
5027 // we set the upload stream above. This means SetRequestMethod() will
5028 // be called twice if ExplicitSetUploadStream() gets called above.
5029
5030 nsAutoCString method;
5031 mRequestHead.Method(method);
5032 config.method = Some(method);
5033
5034 if (mUploadStream) {
5035 // rewind upload stream
5036 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
5037 if (seekable) {
5038 seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
5039 }
5040 config.uploadStream = mUploadStream;
5041 }
5042 config.uploadStreamLength = mReqContentLength;
5043 config.uploadStreamIsStreaming = LoadUploadStreamIsStreaming();
5044
5045 nsAutoCString contentType;
5046 nsresult rv = mRequestHead.GetHeader(nsHttp::Content_Type, contentType);
5047 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5048 config.contentType = Some(contentType);
5049 }
5050
5051 nsAutoCString contentLength;
5052 rv = mRequestHead.GetHeader(nsHttp::Content_Length, contentLength);
5053 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5054 config.contentLength = Some(contentLength);
5055 }
5056 }
5057
5058 return config;
5059}
5060
5061/* static */ void HttpBaseChannel::ConfigureReplacementChannel(
5062 nsIChannel* newChannel, const ReplacementChannelConfig& config,
5063 ReplacementReason aReason) {
5064 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(newChannel));
5065 if (cos) {
5066 cos->SetClassOfService(config.classOfService);
5067 }
5068
5069 // Try to preserve the privacy bit if it has been overridden
5070 if (config.privateBrowsing) {
5071 nsCOMPtr<nsIPrivateBrowsingChannel> newPBChannel =
5072 do_QueryInterface(newChannel);
5073 if (newPBChannel) {
5074 newPBChannel->SetPrivate(*config.privateBrowsing);
5075 }
5076 }
5077
5078 // Transfer the timing data (if we are dealing with an nsITimedChannel).
5079 nsCOMPtr<nsITimedChannel> newTimedChannel(do_QueryInterface(newChannel));
5080 if (config.timedChannelInfo && newTimedChannel) {
5081 // If we're an internal redirect, or a document channel replacement,
5082 // then we shouldn't record any new timing for this and just copy
5083 // over the existing values.
5084 bool shouldHideTiming = aReason != ReplacementReason::Redirect;
5085 if (shouldHideTiming) {
5086 newTimedChannel->SetRedirectCount(
5087 config.timedChannelInfo->redirectCount());
5088 int32_t newCount = config.timedChannelInfo->internalRedirectCount() + 1;
5089 newTimedChannel->SetInternalRedirectCount(std::max(
5090 newCount, static_cast<int32_t>(
5091 config.timedChannelInfo->internalRedirectCount())));
5092 } else {
5093 int32_t newCount = config.timedChannelInfo->redirectCount() + 1;
5094 newTimedChannel->SetRedirectCount(std::max(
5095 newCount,
5096 static_cast<int32_t>(config.timedChannelInfo->redirectCount())));
5097 newTimedChannel->SetInternalRedirectCount(
5098 config.timedChannelInfo->internalRedirectCount());
5099 }
5100
5101 if (shouldHideTiming) {
5102 if (!config.timedChannelInfo->channelCreation().IsNull()) {
5103 newTimedChannel->SetChannelCreation(
5104 config.timedChannelInfo->channelCreation());
5105 }
5106
5107 if (!config.timedChannelInfo->asyncOpen().IsNull()) {
5108 newTimedChannel->SetAsyncOpen(config.timedChannelInfo->asyncOpen());
5109 }
5110 }
5111
5112 // If the RedirectStart is null, we will use the AsyncOpen value of the
5113 // previous channel (this is the first redirect in the redirects chain).
5114 if (config.timedChannelInfo->redirectStart().IsNull()) {
5115 // Only do this for real redirects. Internal redirects should be hidden.
5116 if (!shouldHideTiming) {
5117 newTimedChannel->SetRedirectStart(config.timedChannelInfo->asyncOpen());
5118 }
5119 } else {
5120 newTimedChannel->SetRedirectStart(
5121 config.timedChannelInfo->redirectStart());
5122 }
5123
5124 // For internal redirects just propagate the last redirect end time
5125 // forward. Otherwise the new redirect end time is the last response
5126 // end time.
5127 TimeStamp newRedirectEnd;
5128 if (shouldHideTiming) {
5129 newRedirectEnd = config.timedChannelInfo->redirectEnd();
5130 } else if (!config.timedChannelInfo->responseEnd().IsNull()) {
5131 newRedirectEnd = config.timedChannelInfo->responseEnd();
5132 } else {
5133 newRedirectEnd = TimeStamp::Now();
5134 }
5135 newTimedChannel->SetRedirectEnd(newRedirectEnd);
5136
5137 newTimedChannel->SetInitiatorType(config.timedChannelInfo->initiatorType());
5138
5139 nsCOMPtr<nsILoadInfo> loadInfo = newChannel->LoadInfo();
5140 MOZ_ASSERT(loadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(loadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("loadInfo", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadInfo" ")"
); do { MOZ_CrashSequence(__null, 5140); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5141
5142 newTimedChannel->SetAllRedirectsSameOrigin(
5143 config.timedChannelInfo->allRedirectsSameOrigin());
5144 newTimedChannel->SetAllRedirectsSameOriginIgnoringInternal(
5145 config.timedChannelInfo->allRedirectsSameOriginIgnoringInternal());
5146
5147 if (config.timedChannelInfo->timingAllowCheckForPrincipal()) {
5148 newTimedChannel->SetAllRedirectsPassTimingAllowCheck(
5149 config.timedChannelInfo->allRedirectsPassTimingAllowCheck() &&
5150 *config.timedChannelInfo->timingAllowCheckForPrincipal());
5151 }
5152
5153 // Propagate service worker measurements across redirects. The
5154 // PeformanceResourceTiming.workerStart API expects to see the
5155 // worker start time after a redirect.
5156 newTimedChannel->SetLaunchServiceWorkerStart(
5157 config.timedChannelInfo->launchServiceWorkerStart());
5158 newTimedChannel->SetLaunchServiceWorkerEnd(
5159 config.timedChannelInfo->launchServiceWorkerEnd());
5160 newTimedChannel->SetDispatchFetchEventStart(
5161 config.timedChannelInfo->dispatchFetchEventStart());
5162 newTimedChannel->SetDispatchFetchEventEnd(
5163 config.timedChannelInfo->dispatchFetchEventEnd());
5164 newTimedChannel->SetHandleFetchEventStart(
5165 config.timedChannelInfo->handleFetchEventStart());
5166 newTimedChannel->SetHandleFetchEventEnd(
5167 config.timedChannelInfo->handleFetchEventEnd());
5168 }
5169
5170 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
5171 if (!httpChannel) {
5172 return; // no other options to set
5173 }
5174
5175 if (config.uploadStream) {
5176 nsCOMPtr<nsIUploadChannel2> uploadChannel2 = do_QueryInterface(httpChannel);
5177 // replicate original call to SetUploadStream...
5178 if (uploadChannel2) {
5179 const nsACString& ctype =
5180 config.contentType ? *config.contentType : VoidCString();
5181 // If header is not present mRequestHead.HasHeaderValue will truncated
5182 // it. But we want to end up with a void string, not an empty string,
5183 // because ExplicitSetUploadStream treats the former as "no header" and
5184 // the latter as "header with empty string value".
5185 const nsACString& method = config.method ? *config.method : VoidCString();
5186 if (config.uploadStreamIsStreaming) {
5187 RefPtr<HttpBaseChannel> baseChan = do_QueryObject(httpChannel);
5188 if (baseChan) {
5189 baseChan->SetUploadStreamIsStreaming(true);
5190 }
5191 }
5192 uploadChannel2->ExplicitSetUploadStream(
5193 config.uploadStream, ctype, config.uploadStreamLength, method);
5194 } else if (nsCOMPtr<nsIUploadChannel> uploadChannel =
5195 do_QueryInterface(httpChannel)) {
5196 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" " (" "Should not QI to nsIUploadChannel but not nsIUploadChannel2"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5197); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Should not QI to nsIUploadChannel but not nsIUploadChannel2"
")"); do { MOZ_CrashSequence(__null, 5197); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5197 "Should not QI to nsIUploadChannel but not nsIUploadChannel2")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Should not QI to nsIUploadChannel but not nsIUploadChannel2"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5197); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Should not QI to nsIUploadChannel but not nsIUploadChannel2"
")"); do { MOZ_CrashSequence(__null, 5197); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5198 }
5199 }
5200
5201 if (config.referrerInfo) {
5202 DebugOnly<nsresult> success{};
5203 success = httpChannel->SetReferrerInfo(config.referrerInfo);
5204 MOZ_ASSERT(NS_SUCCEEDED(success))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)
), 1))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)
), 1)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)), 1)))"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 5204
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5204); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5205 }
5206
5207 if (config.method) {
5208 DebugOnly<nsresult> rv = httpChannel->SetRequestMethod(*config.method);
5209 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5209); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5210 }
5211}
5212
5213HttpBaseChannel::ReplacementChannelConfig::ReplacementChannelConfig(
5214 const dom::ReplacementChannelConfigInit& aInit) {
5215 redirectFlags = aInit.redirectFlags();
5216 classOfService = aInit.classOfService();
5217 privateBrowsing = aInit.privateBrowsing();
5218 method = aInit.method();
5219 referrerInfo = aInit.referrerInfo();
5220 timedChannelInfo = aInit.timedChannelInfo();
5221 uploadStream = aInit.uploadStream();
5222 uploadStreamLength = aInit.uploadStreamLength();
5223 uploadStreamIsStreaming = aInit.uploadStreamIsStreaming();
5224 contentType = aInit.contentType();
5225 contentLength = aInit.contentLength();
5226}
5227
5228dom::ReplacementChannelConfigInit
5229HttpBaseChannel::ReplacementChannelConfig::Serialize() {
5230 dom::ReplacementChannelConfigInit config;
5231 config.redirectFlags() = redirectFlags;
5232 config.classOfService() = classOfService;
5233 config.privateBrowsing() = privateBrowsing;
5234 config.method() = method;
5235 config.referrerInfo() = referrerInfo;
5236 config.timedChannelInfo() = timedChannelInfo;
5237 config.uploadStream() =
5238 uploadStream ? RemoteLazyInputStream::WrapStream(uploadStream) : nullptr;
5239 config.uploadStreamLength() = uploadStreamLength;
5240 config.uploadStreamIsStreaming() = uploadStreamIsStreaming;
5241 config.contentType() = contentType;
5242 config.contentLength() = contentLength;
5243
5244 return config;
5245}
5246
5247nsresult HttpBaseChannel::SetupReplacementChannel(nsIURI* newURI,
5248 nsIChannel* newChannel,
5249 bool preserveMethod,
5250 uint32_t redirectFlags) {
5251 nsresult rv;
5252
5253 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetupReplacementChannel " "[this=%p newChannel=%p preserveMethod=%d]"
, this, newChannel, preserveMethod); } } while (0)
5254 ("HttpBaseChannel::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
, "HttpBaseChannel::SetupReplacementChannel " "[this=%p newChannel=%p preserveMethod=%d]"
, this, newChannel, preserveMethod); } } while (0)
5255 "[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
, "HttpBaseChannel::SetupReplacementChannel " "[this=%p newChannel=%p preserveMethod=%d]"
, this, newChannel, preserveMethod); } } while (0)
5256 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
, "HttpBaseChannel::SetupReplacementChannel " "[this=%p newChannel=%p preserveMethod=%d]"
, this, newChannel, preserveMethod); } } while (0)
;
5257
5258 // Ensure the channel's loadInfo's result principal URI so that it's
5259 // either non-null or updated to the redirect target URI.
5260 // We must do this because in case the loadInfo's result principal URI
5261 // is null, it would be taken from OriginalURI of the channel. But we
5262 // overwrite it with the whole redirect chain first URI before opening
5263 // the target channel, hence the information would be lost.
5264 // If the protocol handler that created the channel wants to use
5265 // the originalURI of the channel as the principal URI, this fulfills
5266 // that request - newURI is the original URI of the channel.
5267 nsCOMPtr<nsILoadInfo> newLoadInfo = newChannel->LoadInfo();
5268 nsCOMPtr<nsIURI> resultPrincipalURI;
5269 rv = newLoadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
5270 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5270); return rv; } } while (false)
;
5271 if (!resultPrincipalURI) {
5272 rv = newLoadInfo->SetResultPrincipalURI(newURI);
5273 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5273); return rv; } } while (false)
;
5274 }
5275
5276 nsLoadFlags loadFlags = mLoadFlags;
5277 loadFlags |= LOAD_REPLACE;
5278
5279 // if the original channel was using SSL and this channel is not using
5280 // SSL, then no need to inhibit persistent caching. however, if the
5281 // original channel was not using SSL and has INHIBIT_PERSISTENT_CACHING
5282 // set, then allow the flag to apply to the redirected channel as well.
5283 // since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
5284 // we only need to check if the original channel was using SSL.
5285 if (mURI->SchemeIs("https")) {
5286 loadFlags &= ~INHIBIT_PERSISTENT_CACHING;
5287 }
5288
5289 newChannel->SetLoadFlags(loadFlags);
5290
5291 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
5292
5293 ReplacementReason redirectType =
5294 redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
5295 nsIChannelEventSink::REDIRECT_TRANSPARENT)
5296 ? ReplacementReason::InternalRedirect
5297 : ReplacementReason::Redirect;
5298 ReplacementChannelConfig config = CloneReplacementChannelConfig(
5299 preserveMethod, redirectFlags, redirectType);
5300 ConfigureReplacementChannel(newChannel, config, redirectType);
5301
5302 // Check whether or not this was a cross-domain redirect.
5303 nsCOMPtr<nsITimedChannel> newTimedChannel(do_QueryInterface(newChannel));
5304 bool sameOriginWithOriginalUri = SameOriginWithOriginalUri(newURI);
5305 if (config.timedChannelInfo && newTimedChannel) {
5306 newTimedChannel->SetAllRedirectsSameOrigin(
5307 config.timedChannelInfo->allRedirectsSameOrigin() &&
5308 sameOriginWithOriginalUri);
5309 // Internal redirects (e.g. a service worker serving a response from a
5310 // different URL) are not real cross-origin network hops, so they must not
5311 // count as cross-origin for canvas/CSS/media tainting.
5312 newTimedChannel->SetAllRedirectsSameOriginIgnoringInternal(
5313 config.timedChannelInfo->allRedirectsSameOriginIgnoringInternal() &&
5314 (redirectType == ReplacementReason::InternalRedirect ||
5315 sameOriginWithOriginalUri));
5316 }
5317
5318 newChannel->SetLoadGroup(mLoadGroup);
5319 newChannel->SetNotificationCallbacks(mCallbacks);
5320 // TODO: create tests for cross-origin redirect in bug 1662896.
5321 if (sameOriginWithOriginalUri) {
5322 newChannel->SetContentDisposition(mContentDispositionHint);
5323 if (mContentDispositionFilename) {
5324 newChannel->SetContentDispositionFilename(*mContentDispositionFilename);
5325 }
5326 }
5327
5328 if (!httpChannel) return NS_OK; // no other options to set
5329
5330 // Preserve the CORS preflight information.
5331 nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
5332 if (httpInternal) {
5333 httpInternal->SetLastRedirectFlags(redirectFlags);
5334
5335 if (LoadRequireCORSPreflight()) {
5336 httpInternal->SetCorsPreflightParameters(mUnsafeHeaders, false, false);
5337 }
5338 }
5339
5340 rv = httpChannel->SetAllowSTS(LoadAllowSTS());
5341 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5341); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5341); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5342
5343 // convey the Accept header value
5344 {
5345 nsAutoCString oldAcceptValue;
5346 nsresult hasHeader = mRequestHead.GetHeader(nsHttp::Accept, oldAcceptValue);
5347 if (NS_SUCCEEDED(hasHeader)((bool)(__builtin_expect(!!(!NS_FAILED_impl(hasHeader)), 1)))) {
5348 rv = httpChannel->SetRequestHeader("Accept"_ns, oldAcceptValue, false);
5349 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5349); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5349); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5350 }
5351 }
5352
5353 // convey the User-Agent header value
5354 // since we might be setting custom user agent from DevTools.
5355 if (httpInternal && mRequestMode == RequestMode::No_cors &&
5356 redirectType == ReplacementReason::Redirect) {
5357 nsAutoCString oldUserAgent;
5358 nsresult hasHeader =
5359 mRequestHead.GetHeader(nsHttp::User_Agent, oldUserAgent);
5360 if (NS_SUCCEEDED(hasHeader)((bool)(__builtin_expect(!!(!NS_FAILED_impl(hasHeader)), 1)))) {
5361 rv = httpChannel->SetRequestHeader("User-Agent"_ns, oldUserAgent, false);
5362 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5362); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5363 }
5364 }
5365
5366 // convery the IsUserAgentHeaderModified value.
5367 if (httpInternal) {
5368 rv = httpInternal->SetIsUserAgentHeaderModified(
5369 LoadIsUserAgentHeaderModified());
5370 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5370); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5371 }
5372
5373 // share the request context - see bug 1236650
5374 rv = httpChannel->SetRequestContextID(mRequestContextID);
5375 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5375); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5376
5377 // When on the parent process, the channel can't attempt to get it itself.
5378 // When on the child process, it would be waste to query it again.
5379 rv = httpChannel->SetBrowserId(mBrowserId);
5380 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5380); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5381
5382 // Not setting this flag would break carrying permissions down to the child
5383 // process when the channel is artificially forced to be a main document load.
5384 rv = httpChannel->SetIsMainDocumentChannel(LoadForceMainDocumentChannel());
5385 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5385); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5386
5387 // Preserve the loading order
5388 nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(newChannel);
5389 if (p) {
5390 p->SetPriority(mPriority);
5391 }
5392
5393 if (httpInternal) {
5394 // Convey third party cookie, conservative, and spdy flags.
5395 rv = httpInternal->SetThirdPartyFlags(LoadThirdPartyFlags());
5396 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5396); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5397 rv = httpInternal->SetAllowSpdy(LoadAllowSpdy());
5398 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5398); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5398); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5399 rv = httpInternal->SetAllowHttp3(LoadAllowHttp3());
5400 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5400); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5400); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5401 rv = httpInternal->SetAllowAltSvc(LoadAllowAltSvc());
5402 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5402); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5402); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5403 rv = httpInternal->SetBeConservative(LoadBeConservative());
5404 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5404); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5405 rv = httpInternal->SetIsTRRServiceChannel(LoadIsTRRServiceChannel());
5406 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5406); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5406); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5407 rv = httpInternal->SetTlsFlags(mTlsFlags);
5408 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5408); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5409
5410 // Ensure the type of realChannel involves all types it may redirect to.
5411 // Such as nsHttpChannel and InterceptedChannel.
5412 // Even thought InterceptedChannel itself doesn't require these information,
5413 // it may still be necessary for the following redirections.
5414 // E.g. nsHttpChannel -> InterceptedChannel -> nsHttpChannel
5415 RefPtr<HttpBaseChannel> realChannel;
5416 CallQueryInterface(newChannel, realChannel.StartAssignment());
5417 if (realChannel) {
5418 realChannel->SetTopWindowURI(mTopWindowURI);
5419
5420 realChannel->StoreTaintedOriginFlag(
5421 ShouldTaintReplacementChannelOrigin(newChannel, redirectFlags));
5422 }
5423
5424 // update the DocumentURI indicator since we are being redirected.
5425 // if this was a top-level document channel, then the new channel
5426 // should have its mDocumentURI point to newURI; otherwise, we
5427 // just need to pass along our mDocumentURI to the new channel.
5428 if (newURI && (mURI == mDocumentURI)) {
5429 rv = httpInternal->SetDocumentURI(newURI);
5430 } else {
5431 rv = httpInternal->SetDocumentURI(mDocumentURI);
5432 }
5433 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5433); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5434
5435 // if there is a chain of keys for redirect-responses we transfer it to
5436 // the new channel (see bug #561276)
5437 {
5438 auto redirectedCachekeys = mRedirectedCachekeys.Lock();
5439 auto& ref = redirectedCachekeys.ref();
5440 if (ref) {
5441 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetupReplacementChannel " "[this=%p] transferring chain of redirect cache-keys"
, this); } } while (0)
5442 ("HttpBaseChannel::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
, "HttpBaseChannel::SetupReplacementChannel " "[this=%p] transferring chain of redirect cache-keys"
, this); } } while (0)
5443 "[this=%p] transferring chain of redirect cache-keys",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetupReplacementChannel " "[this=%p] transferring chain of redirect cache-keys"
, this); } } while (0)
5444 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetupReplacementChannel " "[this=%p] transferring chain of redirect cache-keys"
, this); } } while (0)
;
5445 rv = httpInternal->SetCacheKeysRedirectChain(ref.release());
5446 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5446); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5446); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5447 }
5448 }
5449
5450 // Preserve Request mode.
5451 rv = httpInternal->SetRequestMode(mRequestMode);
5452 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5452); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5453
5454 // Preserve Redirect mode flag.
5455 rv = httpInternal->SetRedirectMode(mRedirectMode);
5456 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5456); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5457
5458 httpInternal->SetAltDataForChild(LoadAltDataForChild());
5459 if (LoadDisableAltDataCache()) {
5460 httpInternal->DisableAltDataCache();
5461 }
5462 }
5463
5464 // transfer any properties
5465 nsCOMPtr<nsIWritablePropertyBag> bag(do_QueryInterface(newChannel));
5466 if (bag) {
5467 for (const auto& entry : mPropertyHash) {
5468 bag->SetProperty(entry.GetKey(), entry.GetWeak());
5469 }
5470 }
5471
5472 // Pass the preferred alt-data type on to the new channel.
5473 nsCOMPtr<nsICacheInfoChannel> cacheInfoChan(do_QueryInterface(newChannel));
5474 if (cacheInfoChan) {
5475 for (auto& data : mPreferredCachedAltDataTypes) {
5476 cacheInfoChan->PreferAlternativeDataType(data.type(), data.contentType(),
5477 data.deliverAltData());
5478 }
5479
5480 if (LoadForceValidateCacheContent()) {
5481 (void)cacheInfoChan->SetForceValidateCacheContent(true);
5482 }
5483 }
5484
5485 if (redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
5486 nsIChannelEventSink::REDIRECT_STS_UPGRADE)) {
5487 // Copy non-origin related headers to the new channel.
5488 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
5489 new AddHeadersToChannelVisitor(httpChannel);
5490 rv = mRequestHead.VisitHeaders(visitor);
5491 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5491); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5491); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5492 }
5493
5494 // we need to strip Authentication headers for cross-origin requests
5495 // Ref: https://fetch.spec.whatwg.org/#http-redirect-fetch
5496 nsAutoCString authHeader;
5497 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(httpChannel->GetRequestHeader
("Authorization"_ns, authHeader))), 1)))
5498 httpChannel->GetRequestHeader("Authorization"_ns, authHeader))((bool)(__builtin_expect(!!(!NS_FAILED_impl(httpChannel->GetRequestHeader
("Authorization"_ns, authHeader))), 1)))
&&
5499 NS_ShouldRemoveAuthHeaderOnRedirect(static_cast<nsIChannel*>(this),
5500 newChannel, redirectFlags)) {
5501 rv = httpChannel->SetRequestHeader("Authorization"_ns, ""_ns, false);
5502 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5502); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5503 }
5504
5505 return NS_OK;
5506}
5507
5508// check whether the new channel is of same origin as the current channel
5509bool HttpBaseChannel::IsNewChannelSameOrigin(nsIChannel* aNewChannel) {
5510 bool isSameOrigin = false;
5511 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5512
5513 if (!ssm) {
5514 return false;
5515 }
5516
5517 nsCOMPtr<nsIURI> newURI;
5518 NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(newURI));
5519
5520 nsresult rv = ssm->CheckSameOriginURI(newURI, mURI, false, false);
5521 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5522 isSameOrigin = true;
5523 }
5524
5525 return isSameOrigin;
5526}
5527
5528bool HttpBaseChannel::ShouldTaintReplacementChannelOrigin(
5529 nsIChannel* aNewChannel, uint32_t aRedirectFlags) {
5530 if (LoadTaintedOriginFlag()) {
5531 return true;
5532 }
5533
5534 if (NS_IsInternalSameURIRedirect(this, aNewChannel, aRedirectFlags) ||
5535 NS_IsHSTSUpgradeRedirect(this, aNewChannel, aRedirectFlags)) {
5536 return false;
5537 }
5538
5539 // Fetch spec "compute redirect-taint":
5540 // Taint if url's origin is not same-origin with lastURL's origin AND
5541 // request's origin is not same-origin with lastURL's origin.
5542 // Condition 1: same-origin redirect never taints.
5543 if (IsNewChannelSameOrigin(aNewChannel)) {
5544 return false;
5545 }
5546
5547 // Condition 2: cross-origin redirect — taint if the origin that initiated
5548 // the request is not same-origin with the current URL (mURI).
5549 //
5550 // Bug 1965430: For top-level navigational loads (e.g., form POST),
5551 // LoadingPrincipal is null. TriggeringPrincipal correctly represents the
5552 // origin that initiated the request in all cases. The old code using
5553 // LoadingPrincipal fell through to comparing mOriginalURI with mURI, which
5554 // are equal for the first redirect, incorrectly skipping the taint.
5555 if (StaticPrefs::network_http_origin_useTriggeringPrincipal()) {
5556 nsIPrincipal* triggeringPrincipal = mLoadInfo->TriggeringPrincipal();
5557 if (!triggeringPrincipal) {
5558 return true;
5559 }
5560 bool sameOrigin = false;
5561 nsresult rv = triggeringPrincipal->IsSameOrigin(mURI, &sameOrigin);
5562 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5563 return true;
5564 }
5565 return !sameOrigin;
5566 }
5567
5568 // Old code path (Bug 1965430): retained behind pref for safety.
5569 // Uses LoadingPrincipal which is null for top-level navigations,
5570 // falling back to mOriginalURI vs mURI comparison.
5571 nsresult rv;
5572 if (mLoadInfo->GetLoadingPrincipal()) {
5573 bool sameOrigin = false;
5574 rv = mLoadInfo->GetLoadingPrincipal()->IsSameOrigin(mURI, &sameOrigin);
5575 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5576 return true;
5577 }
5578 return !sameOrigin;
5579 }
5580 if (!mOriginalURI) {
5581 return true;
5582 }
5583
5584 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5585 if (!ssm) {
5586 return true;
5587 }
5588
5589 rv = ssm->CheckSameOriginURI(mOriginalURI, mURI, false, false);
5590 return NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)));
5591}
5592
5593// Redirect Tracking
5594bool HttpBaseChannel::SameOriginWithOriginalUri(nsIURI* aURI) {
5595 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5596 bool isPrivateWin = mLoadInfo->GetOriginAttributes().IsPrivateBrowsing();
5597 nsresult rv =
5598 ssm->CheckSameOriginURI(aURI, mOriginalURI, false, isPrivateWin);
5599 return (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))));
5600}
5601
5602//-----------------------------------------------------------------------------
5603// HttpBaseChannel::nsIClassifiedChannel
5604
5605NS_IMETHODIMPnsresult
5606HttpBaseChannel::GetMatchedList(nsACString& aList) {
5607 aList = mMatchedList;
5608 return NS_OK;
5609}
5610
5611NS_IMETHODIMPnsresult
5612HttpBaseChannel::GetMatchedProvider(nsACString& aProvider) {
5613 aProvider = mMatchedProvider;
5614 return NS_OK;
5615}
5616
5617NS_IMETHODIMPnsresult
5618HttpBaseChannel::GetMatchedFullHash(nsACString& aFullHash) {
5619 aFullHash = mMatchedFullHash;
5620 return NS_OK;
5621}
5622
5623NS_IMETHODIMPnsresult
5624HttpBaseChannel::SetMatchedInfo(const nsACString& aList,
5625 const nsACString& aProvider,
5626 const nsACString& aFullHash) {
5627 NS_ENSURE_ARG(!aList.IsEmpty())do { if ((__builtin_expect(!!(!(!aList.IsEmpty())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!aList.IsEmpty()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5627); return NS_ERROR_INVALID_ARG; } } while (false)
;
5628
5629 mMatchedList = aList;
5630 mMatchedProvider = aProvider;
5631 mMatchedFullHash = aFullHash;
5632 return NS_OK;
5633}
5634
5635NS_IMETHODIMPnsresult
5636HttpBaseChannel::GetMatchedTrackingLists(nsTArray<nsCString>& aLists) {
5637 aLists = mMatchedTrackingLists.Clone();
5638 return NS_OK;
5639}
5640
5641NS_IMETHODIMPnsresult
5642HttpBaseChannel::GetMatchedTrackingFullHashes(
5643 nsTArray<nsCString>& aFullHashes) {
5644 aFullHashes = mMatchedTrackingFullHashes.Clone();
5645 return NS_OK;
5646}
5647
5648NS_IMETHODIMPnsresult
5649HttpBaseChannel::SetMatchedTrackingInfo(
5650 const nsTArray<nsCString>& aLists, const nsTArray<nsCString>& aFullHashes) {
5651 NS_ENSURE_ARG(!aLists.IsEmpty())do { if ((__builtin_expect(!!(!(!aLists.IsEmpty())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!aLists.IsEmpty()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5651); return NS_ERROR_INVALID_ARG; } } while (false)
;
5652 // aFullHashes can be empty for non hash-matching algorithm, for example,
5653 // host based test entries in preference.
5654
5655 mMatchedTrackingLists = aLists.Clone();
5656 mMatchedTrackingFullHashes = aFullHashes.Clone();
5657 return NS_OK;
5658}
5659//-----------------------------------------------------------------------------
5660// HttpBaseChannel::nsITimedChannel
5661//-----------------------------------------------------------------------------
5662
5663NS_IMETHODIMPnsresult
5664HttpBaseChannel::GetChannelCreation(TimeStamp* _retval) {
5665 *_retval = mChannelCreationTimestamp;
5666 return NS_OK;
5667}
5668
5669NS_IMETHODIMPnsresult
5670HttpBaseChannel::SetChannelCreation(TimeStamp aValue) {
5671 MOZ_DIAGNOSTIC_ASSERT(!aValue.IsNull())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aValue.IsNull())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aValue.IsNull()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!aValue.IsNull()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 5671
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aValue.IsNull()"
")"); do { MOZ_CrashSequence(__null, 5671); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5672 TimeDuration adjust = aValue - mChannelCreationTimestamp;
5673 mChannelCreationTimestamp = aValue;
5674 mChannelCreationTime += (PRTime)adjust.ToMicroseconds();
5675 return NS_OK;
5676}
5677
5678NS_IMETHODIMPnsresult
5679HttpBaseChannel::GetAsyncOpen(TimeStamp* _retval) {
5680 *_retval = mAsyncOpenTime;
5681 return NS_OK;
5682}
5683
5684NS_IMETHODIMPnsresult
5685HttpBaseChannel::SetAsyncOpen(TimeStamp aValue) {
5686 MOZ_DIAGNOSTIC_ASSERT(!aValue.IsNull())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aValue.IsNull())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aValue.IsNull()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!aValue.IsNull()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 5686
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aValue.IsNull()"
")"); do { MOZ_CrashSequence(__null, 5686); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5687 mAsyncOpenTime = aValue;
5688 StoreAsyncOpenTimeOverriden(true);
5689 return NS_OK;
5690}
5691
5692/**
5693 * @return the number of redirects. There is no check for cross-domain
5694 * redirects. This check must be done by the consumers.
5695 */
5696NS_IMETHODIMPnsresult
5697HttpBaseChannel::GetRedirectCount(uint8_t* aRedirectCount) {
5698 *aRedirectCount = mRedirectCount;
5699 return NS_OK;
5700}
5701
5702NS_IMETHODIMPnsresult
5703HttpBaseChannel::SetRedirectCount(uint8_t aRedirectCount) {
5704 mRedirectCount = aRedirectCount;
5705 return NS_OK;
5706}
5707
5708NS_IMETHODIMPnsresult
5709HttpBaseChannel::GetInternalRedirectCount(uint8_t* aRedirectCount) {
5710 *aRedirectCount = mInternalRedirectCount;
5711 return NS_OK;
5712}
5713
5714NS_IMETHODIMPnsresult
5715HttpBaseChannel::SetInternalRedirectCount(uint8_t aRedirectCount) {
5716 mInternalRedirectCount = aRedirectCount;
5717 return NS_OK;
5718}
5719
5720NS_IMETHODIMPnsresult
5721HttpBaseChannel::GetRedirectStart(TimeStamp* _retval) {
5722 *_retval = mRedirectStartTimeStamp;
5723 return NS_OK;
5724}
5725
5726NS_IMETHODIMPnsresult
5727HttpBaseChannel::SetRedirectStart(TimeStamp aRedirectStart) {
5728 mRedirectStartTimeStamp = aRedirectStart;
5729 return NS_OK;
5730}
5731
5732NS_IMETHODIMPnsresult
5733HttpBaseChannel::GetRedirectEnd(TimeStamp* _retval) {
5734 *_retval = mRedirectEndTimeStamp;
5735 return NS_OK;
5736}
5737
5738NS_IMETHODIMPnsresult
5739HttpBaseChannel::SetRedirectEnd(TimeStamp aRedirectEnd) {
5740 mRedirectEndTimeStamp = aRedirectEnd;
5741 return NS_OK;
5742}
5743
5744NS_IMETHODIMPnsresult
5745HttpBaseChannel::GetAllRedirectsSameOrigin(bool* aAllRedirectsSameOrigin) {
5746 *aAllRedirectsSameOrigin = LoadAllRedirectsSameOrigin();
5747 return NS_OK;
5748}
5749
5750NS_IMETHODIMPnsresult
5751HttpBaseChannel::SetAllRedirectsSameOrigin(bool aAllRedirectsSameOrigin) {
5752 StoreAllRedirectsSameOrigin(aAllRedirectsSameOrigin);
5753 return NS_OK;
5754}
5755
5756NS_IMETHODIMPnsresult
5757HttpBaseChannel::GetAllRedirectsSameOriginIgnoringInternal(
5758 bool* aAllRedirectsSameOriginIgnoringInternal) {
5759 *aAllRedirectsSameOriginIgnoringInternal =
5760 LoadAllRedirectsSameOriginIgnoringInternal();
5761 return NS_OK;
5762}
5763
5764NS_IMETHODIMPnsresult
5765HttpBaseChannel::SetAllRedirectsSameOriginIgnoringInternal(
5766 bool aAllRedirectsSameOriginIgnoringInternal) {
5767 StoreAllRedirectsSameOriginIgnoringInternal(
5768 aAllRedirectsSameOriginIgnoringInternal);
5769 return NS_OK;
5770}
5771
5772NS_IMETHODIMPnsresult
5773HttpBaseChannel::GetAllRedirectsPassTimingAllowCheck(bool* aPassesCheck) {
5774 *aPassesCheck = LoadAllRedirectsPassTimingAllowCheck();
5775 return NS_OK;
5776}
5777
5778NS_IMETHODIMPnsresult
5779HttpBaseChannel::SetAllRedirectsPassTimingAllowCheck(bool aPassesCheck) {
5780 StoreAllRedirectsPassTimingAllowCheck(aPassesCheck);
5781 return NS_OK;
5782}
5783
5784// https://fetch.spec.whatwg.org/#cors-check
5785bool HttpBaseChannel::PerformCORSCheck() {
5786 // Step 1
5787 // Let origin be the result of getting `Access-Control-Allow-Origin`
5788 // from response’s header list.
5789 nsAutoCString origin;
5790 nsresult rv = GetResponseHeader("Access-Control-Allow-Origin"_ns, origin);
5791
5792 // Step 2
5793 // If origin is null, then return failure. (Note: null, not 'null').
5794 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || origin.IsVoid()) {
5795 return false;
5796 }
5797
5798 // Step 3
5799 // If request’s credentials mode is not "include"
5800 // and origin is `*`, then return success.
5801 uint32_t cookiePolicy = mLoadInfo->GetCookiePolicy();
5802 if (cookiePolicy != nsILoadInfo::SEC_COOKIES_INCLUDE &&
5803 origin.EqualsLiteral("*")) {
5804 return true;
5805 }
5806
5807 // Step 4
5808 // If the result of byte-serializing a request origin
5809 // with request is not origin, then return failure.
5810 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5811 nsCOMPtr<nsIPrincipal> resourcePrincipal;
5812 rv = ssm->GetChannelURIPrincipal(this, getter_AddRefs(resourcePrincipal));
5813 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !resourcePrincipal) {
5814 return false;
5815 }
5816 nsAutoCString serializedOrigin;
5817 nsContentSecurityManager::GetSerializedOrigin(
5818 mLoadInfo->TriggeringPrincipal(), resourcePrincipal, serializedOrigin,
5819 mLoadInfo);
5820 if (!serializedOrigin.Equals(origin)) {
5821 return false;
5822 }
5823
5824 // Step 5
5825 // If request’s credentials mode is not "include", then return success.
5826 if (cookiePolicy != nsILoadInfo::SEC_COOKIES_INCLUDE) {
5827 return true;
5828 }
5829
5830 // Step 6
5831 // Let credentials be the result of getting
5832 // `Access-Control-Allow-Credentials` from response’s header list.
5833 nsAutoCString credentials;
5834 rv = GetResponseHeader("Access-Control-Allow-Credentials"_ns, credentials);
5835
5836 // Step 7 and 8
5837 // If credentials is `true`, then return success.
5838 // (else) return failure.
5839 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && credentials.EqualsLiteral("true");
5840}
5841
5842NS_IMETHODIMPnsresult
5843HttpBaseChannel::BodyInfoAccessAllowedCheck(nsIPrincipal* aOrigin,
5844 BodyInfoAccess* _retval) {
5845 // Per the Fetch spec, https://fetch.spec.whatwg.org/#response-body-info,
5846 // the bodyInfo for Resource Timing and Navigation Timing info consists of
5847 // encoded size, decoded size, and content type. It is however made opaque
5848 // whenever the response is turned into a network error, which sets its
5849 // bodyInfo to its default values (sizes=0, content-type="").
5850
5851 // Case 1:
5852 // "no-cors" -> Upon success, fetch will return an opaque filtered response.
5853 // An opaque(-redirect) filtered response is a filtered response
5854 // whose ... body info is a new response body info.
5855 auto tainting = mLoadInfo->GetTainting();
5856 if (tainting == mozilla::LoadTainting::Opaque) {
5857 *_retval = BodyInfoAccess::DISALLOWED;
5858 return NS_OK;
5859 }
5860
5861 // Case 2:
5862 // If request’s response tainting is "cors" and a CORS check for request
5863 // and response returns failure, then return a network error.
5864 if (tainting == mozilla::LoadTainting::CORS && !PerformCORSCheck()) {
5865 *_retval = BodyInfoAccess::DISALLOWED;
5866 return NS_OK;
5867 }
5868
5869 // Otherwise:
5870 // The fetch response handover, given a fetch params fetchParams
5871 // and a response response, run these steps:
5872 // processResponseEndOfBody:
5873 // - If fetchParams’s request’s mode is not "navigate" or response’s
5874 // has-cross-origin-redirects is false:
5875 // - Let mimeType be the result of extracting a MIME type from
5876 // response’s header list.
5877 // - If mimeType is not failure, then set bodyInfo’s content type to the
5878 // result of minimizing a supported MIME type given mimeType.
5879 dom::RequestMode requestMode;
5880 MOZ_ALWAYS_SUCCEEDS(GetRequestMode(&requestMode))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(GetRequestMode(&requestMode))), 1)))), 1))) { } else { do
{ do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(GetRequestMode(&requestMode))"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 5880
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(GetRequestMode(&requestMode))"
")"); do { MOZ_CrashSequence(__null, 5880); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
5881 if (requestMode != RequestMode::Navigate || LoadAllRedirectsSameOrigin()) {
5882 *_retval = BodyInfoAccess::ALLOW_ALL;
5883 return NS_OK;
5884 }
5885
5886 *_retval = BodyInfoAccess::ALLOW_SIZES;
5887 return NS_OK;
5888}
5889
5890// https://fetch.spec.whatwg.org/#tao-check
5891NS_IMETHODIMPnsresult
5892HttpBaseChannel::TimingAllowCheck(nsIPrincipal* aOrigin, bool* _retval) {
5893 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5894 nsCOMPtr<nsIPrincipal> resourcePrincipal;
5895 nsresult rv =
5896 ssm->GetChannelURIPrincipal(this, getter_AddRefs(resourcePrincipal));
5897 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !resourcePrincipal || !aOrigin) {
5898 *_retval = false;
5899 return NS_OK;
5900 }
5901
5902 bool sameOrigin = false;
5903 rv = resourcePrincipal->Equals(aOrigin, &sameOrigin);
Value stored to 'rv' is never read
5904
5905 nsAutoCString serializedOrigin;
5906 nsContentSecurityManager::GetSerializedOrigin(aOrigin, resourcePrincipal,
5907 serializedOrigin, mLoadInfo);
5908
5909 // All redirects are same origin
5910 if (sameOrigin && (!serializedOrigin.IsEmpty() &&
5911 !serializedOrigin.EqualsLiteral("null"))) {
5912 *_retval = true;
5913 return NS_OK;
5914 }
5915
5916 nsAutoCString headerValue;
5917 rv = GetResponseHeader("Timing-Allow-Origin"_ns, headerValue);
5918 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5919 *_retval = false;
5920 return NS_OK;
5921 }
5922
5923 Tokenizer p(headerValue);
5924 Tokenizer::Token t;
5925
5926 p.Record();
5927 nsAutoCString headerItem;
5928 while (p.Next(t)) {
5929 if (t.Type() == Tokenizer::TOKEN_EOF ||
5930 t.Equals(Tokenizer::Token::Char(','))) {
5931 p.Claim(headerItem);
5932 nsHttp::TrimHTTPWhitespace(headerItem, headerItem);
5933 // If the list item contains a case-sensitive match for the value of the
5934 // origin, or a wildcard, return pass
5935 if (headerItem == serializedOrigin || headerItem == "*") {
5936 *_retval = true;
5937 return NS_OK;
5938 }
5939 // We start recording again for the following items in the list
5940 p.Record();
5941 }
5942 }
5943
5944 *_retval = false;
5945 return NS_OK;
5946}
5947
5948NS_IMETHODIMPnsresult
5949HttpBaseChannel::GetLaunchServiceWorkerStart(TimeStamp* _retval) {
5950 MOZ_ASSERT(_retval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(_retval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(_retval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("_retval", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 5950); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5951 *_retval = mLaunchServiceWorkerStart;
5952 return NS_OK;
5953}
5954
5955NS_IMETHODIMPnsresult
5956HttpBaseChannel::SetLaunchServiceWorkerStart(TimeStamp aTimeStamp) {
5957 mLaunchServiceWorkerStart = aTimeStamp;
5958 return NS_OK;
5959}
5960
5961NS_IMETHODIMPnsresult
5962HttpBaseChannel::GetLaunchServiceWorkerEnd(TimeStamp* _retval) {
5963 MOZ_ASSERT(_retval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(_retval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(_retval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("_retval", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5963); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 5963); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5964 *_retval = mLaunchServiceWorkerEnd;
5965 return NS_OK;
5966}
5967
5968NS_IMETHODIMPnsresult
5969HttpBaseChannel::SetLaunchServiceWorkerEnd(TimeStamp aTimeStamp) {
5970 mLaunchServiceWorkerEnd = aTimeStamp;
5971 return NS_OK;
5972}
5973
5974NS_IMETHODIMPnsresult
5975HttpBaseChannel::GetDispatchFetchEventStart(TimeStamp* _retval) {
5976 MOZ_ASSERT(_retval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(_retval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(_retval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("_retval", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 5976); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5977 *_retval = mDispatchFetchEventStart;
5978 return NS_OK;
5979}
5980
5981NS_IMETHODIMPnsresult
5982HttpBaseChannel::SetDispatchFetchEventStart(TimeStamp aTimeStamp) {
5983 mDispatchFetchEventStart = aTimeStamp;
5984 return NS_OK;
5985}
5986
5987NS_IMETHODIMPnsresult
5988HttpBaseChannel::GetDispatchFetchEventEnd(TimeStamp* _retval) {
5989 MOZ_ASSERT(_retval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(_retval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(_retval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("_retval", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 5989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 5989); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5990 *_retval = mDispatchFetchEventEnd;
5991 return NS_OK;
5992}
5993
5994NS_IMETHODIMPnsresult
5995HttpBaseChannel::SetDispatchFetchEventEnd(TimeStamp aTimeStamp) {
5996 mDispatchFetchEventEnd = aTimeStamp;
5997 return NS_OK;
5998}
5999
6000NS_IMETHODIMPnsresult
6001HttpBaseChannel::GetHandleFetchEventStart(TimeStamp* _retval) {
6002 MOZ_ASSERT(_retval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(_retval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(_retval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("_retval", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 6002); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6003 *_retval = mHandleFetchEventStart;
6004 return NS_OK;
6005}
6006
6007NS_IMETHODIMPnsresult
6008HttpBaseChannel::SetHandleFetchEventStart(TimeStamp aTimeStamp) {
6009 mHandleFetchEventStart = aTimeStamp;
6010 return NS_OK;
6011}
6012
6013NS_IMETHODIMPnsresult
6014HttpBaseChannel::GetHandleFetchEventEnd(TimeStamp* _retval) {
6015 MOZ_ASSERT(_retval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(_retval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(_retval))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("_retval", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 6015); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6016 *_retval = mHandleFetchEventEnd;
6017 return NS_OK;
6018}
6019
6020NS_IMETHODIMPnsresult
6021HttpBaseChannel::SetHandleFetchEventEnd(TimeStamp aTimeStamp) {
6022 mHandleFetchEventEnd = aTimeStamp;
6023 return NS_OK;
6024}
6025
6026NS_IMETHODIMPnsresult
6027HttpBaseChannel::GetDomainLookupStart(TimeStamp* _retval) {
6028 *_retval = mTransactionTimings.domainLookupStart;
6029 return NS_OK;
6030}
6031
6032NS_IMETHODIMPnsresult
6033HttpBaseChannel::GetDomainLookupEnd(TimeStamp* _retval) {
6034 *_retval = mTransactionTimings.domainLookupEnd;
6035 return NS_OK;
6036}
6037
6038NS_IMETHODIMPnsresult
6039HttpBaseChannel::GetConnectStart(TimeStamp* _retval) {
6040 *_retval = mTransactionTimings.connectStart;
6041 return NS_OK;
6042}
6043
6044NS_IMETHODIMPnsresult
6045HttpBaseChannel::GetTcpConnectEnd(TimeStamp* _retval) {
6046 *_retval = mTransactionTimings.tcpConnectEnd;
6047 return NS_OK;
6048}
6049
6050NS_IMETHODIMPnsresult
6051HttpBaseChannel::GetSecureConnectionStart(TimeStamp* _retval) {
6052 *_retval = mTransactionTimings.secureConnectionStart;
6053 return NS_OK;
6054}
6055
6056NS_IMETHODIMPnsresult
6057HttpBaseChannel::GetConnectEnd(TimeStamp* _retval) {
6058 *_retval = mTransactionTimings.connectEnd;
6059 return NS_OK;
6060}
6061
6062NS_IMETHODIMPnsresult
6063HttpBaseChannel::GetRequestStart(TimeStamp* _retval) {
6064 *_retval = mTransactionTimings.requestStart;
6065 return NS_OK;
6066}
6067
6068NS_IMETHODIMPnsresult
6069HttpBaseChannel::GetResponseStart(TimeStamp* _retval) {
6070 *_retval = mTransactionTimings.responseStart;
6071 return NS_OK;
6072}
6073
6074NS_IMETHODIMPnsresult
6075HttpBaseChannel::GetFirstInterimResponseStart(TimeStamp* _retval) {
6076 *_retval = mTransactionTimings.firstInterimResponseStart;
6077 return NS_OK;
6078}
6079
6080NS_IMETHODIMPnsresult
6081HttpBaseChannel::GetFinalResponseHeadersStart(TimeStamp* _retval) {
6082 *_retval = mTransactionTimings.finalResponseHeadersStart;
6083 return NS_OK;
6084}
6085
6086NS_IMETHODIMPnsresult
6087HttpBaseChannel::GetResponseEnd(TimeStamp* _retval) {
6088 *_retval = mTransactionTimings.responseEnd;
6089 return NS_OK;
6090}
6091
6092NS_IMETHODIMPnsresult
6093HttpBaseChannel::GetCacheReadStart(TimeStamp* _retval) {
6094 *_retval = mCacheReadStart;
6095 return NS_OK;
6096}
6097
6098NS_IMETHODIMPnsresult
6099HttpBaseChannel::GetCacheReadEnd(TimeStamp* _retval) {
6100 *_retval = mCacheReadEnd;
6101 return NS_OK;
6102}
6103
6104NS_IMETHODIMPnsresult
6105HttpBaseChannel::GetTransactionPending(TimeStamp* _retval) {
6106 *_retval = mTransactionTimings.transactionPending;
6107 return NS_OK;
6108}
6109
6110NS_IMETHODIMPnsresult
6111HttpBaseChannel::GetInitiatorType(nsAString& aInitiatorType) {
6112 aInitiatorType = mInitiatorType;
6113 return NS_OK;
6114}
6115
6116NS_IMETHODIMPnsresult
6117HttpBaseChannel::SetInitiatorType(const nsAString& aInitiatorType) {
6118 mInitiatorType = aInitiatorType;
6119 return NS_OK;
6120}
6121
6122#define IMPL_TIMING_ATTR(name) \
6123 NS_IMETHODIMPnsresult \
6124 HttpBaseChannel::Get##name##Time(PRTime* _retval) { \
6125 TimeStamp stamp; \
6126 Get##name(&stamp); \
6127 if (stamp.IsNull()) { \
6128 *_retval = 0; \
6129 return NS_OK; \
6130 } \
6131 *_retval = \
6132 mChannelCreationTime + \
6133 (PRTime)((stamp - mChannelCreationTimestamp).ToSeconds() * 1e6); \
6134 return NS_OK; \
6135 }
6136
6137IMPL_TIMING_ATTR(ChannelCreation)
6138IMPL_TIMING_ATTR(AsyncOpen)
6139IMPL_TIMING_ATTR(LaunchServiceWorkerStart)
6140IMPL_TIMING_ATTR(LaunchServiceWorkerEnd)
6141IMPL_TIMING_ATTR(DispatchFetchEventStart)
6142IMPL_TIMING_ATTR(DispatchFetchEventEnd)
6143IMPL_TIMING_ATTR(HandleFetchEventStart)
6144IMPL_TIMING_ATTR(HandleFetchEventEnd)
6145IMPL_TIMING_ATTR(DomainLookupStart)
6146IMPL_TIMING_ATTR(DomainLookupEnd)
6147IMPL_TIMING_ATTR(ConnectStart)
6148IMPL_TIMING_ATTR(TcpConnectEnd)
6149IMPL_TIMING_ATTR(SecureConnectionStart)
6150IMPL_TIMING_ATTR(ConnectEnd)
6151IMPL_TIMING_ATTR(RequestStart)
6152IMPL_TIMING_ATTR(ResponseStart)
6153IMPL_TIMING_ATTR(FirstInterimResponseStart)
6154IMPL_TIMING_ATTR(FinalResponseHeadersStart)
6155IMPL_TIMING_ATTR(ResponseEnd)
6156IMPL_TIMING_ATTR(CacheReadStart)
6157IMPL_TIMING_ATTR(CacheReadEnd)
6158IMPL_TIMING_ATTR(RedirectStart)
6159IMPL_TIMING_ATTR(RedirectEnd)
6160IMPL_TIMING_ATTR(TransactionPending)
6161
6162#undef IMPL_TIMING_ATTR
6163
6164void HttpBaseChannel::MaybeReportTimingData() {
6165 // There is no point in continuing, since the performance object in the parent
6166 // isn't the same as the one in the child which will be reporting resource
6167 // performance.
6168 if (XRE_IsE10sParentProcess()) {
6169 return;
6170 }
6171
6172 // Devtools can create fetch requests on behalf the content document.
6173 // If we don't exclude these requests, they'd also be reported
6174 // to the content document.
6175 bool isInDevToolsContext;
6176 mLoadInfo->GetIsInDevToolsContext(&isInDevToolsContext);
6177 if (isInDevToolsContext) {
6178 return;
6179 }
6180
6181 mozilla::dom::PerformanceStorage* documentPerformance =
6182 mLoadInfo->GetPerformanceStorage();
6183 if (documentPerformance) {
6184 documentPerformance->AddEntry(this, this);
6185 return;
6186 }
6187
6188 if (!nsGlobalWindowInner::GetInnerWindowWithId(
6189 mLoadInfo->GetInnerWindowID())) {
6190 // The inner window is in a different process.
6191 dom::ContentChild* child = dom::ContentChild::GetSingleton();
6192
6193 if (!child) {
6194 return;
6195 }
6196 nsAutoString initiatorType;
6197 nsAutoString entryName;
6198
6199 UniquePtr<dom::PerformanceTimingData> performanceTimingData(
6200 dom::PerformanceTimingData::Create(this, this, 0, initiatorType,
6201 entryName));
6202 if (!performanceTimingData) {
6203 return;
6204 }
6205
6206 LoadInfoArgs loadInfoArgs;
6207 mozilla::ipc::LoadInfoToLoadInfoArgs(mLoadInfo, &loadInfoArgs);
6208 child->SendReportFrameTimingData(loadInfoArgs, entryName, initiatorType,
6209 std::move(performanceTimingData));
6210 }
6211}
6212
6213NS_IMETHODIMPnsresult
6214HttpBaseChannel::SetReportResourceTiming(bool enabled) {
6215 StoreReportTiming(enabled);
6216 return NS_OK;
6217}
6218
6219NS_IMETHODIMPnsresult
6220HttpBaseChannel::GetReportResourceTiming(bool* _retval) {
6221 *_retval = LoadReportTiming();
6222 return NS_OK;
6223}
6224
6225nsIURI* HttpBaseChannel::GetReferringPage() {
6226 nsCOMPtr<nsPIDOMWindowInner> pDomWindow = GetInnerDOMWindow();
6227 if (!pDomWindow) {
6228 return nullptr;
6229 }
6230 return pDomWindow->GetDocumentURI();
6231}
6232
6233nsPIDOMWindowInner* HttpBaseChannel::GetInnerDOMWindow() {
6234 nsCOMPtr<nsILoadContext> loadContext;
6235 NS_QueryNotificationCallbacks(this, loadContext);
6236 if (!loadContext) {
6237 return nullptr;
6238 }
6239 nsCOMPtr<mozIDOMWindowProxy> domWindow;
6240 loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
6241 if (!domWindow) {
6242 return nullptr;
6243 }
6244 auto* pDomWindow = nsPIDOMWindowOuter::From(domWindow);
6245 if (!pDomWindow) {
6246 return nullptr;
6247 }
6248 nsCOMPtr<nsPIDOMWindowInner> innerWindow =
6249 pDomWindow->GetCurrentInnerWindow();
6250 if (!innerWindow) {
6251 return nullptr;
6252 }
6253
6254 return innerWindow;
6255}
6256
6257//-----------------------------------------------------------------------------
6258// HttpBaseChannel::nsIThrottledInputChannel
6259//-----------------------------------------------------------------------------
6260
6261NS_IMETHODIMPnsresult
6262HttpBaseChannel::SetThrottleQueue(nsIInputChannelThrottleQueue* aQueue) {
6263 if (!XRE_IsParentProcess()) {
6264 return NS_ERROR_FAILURE;
6265 }
6266
6267 mThrottleQueue = aQueue;
6268 return NS_OK;
6269}
6270
6271NS_IMETHODIMPnsresult
6272HttpBaseChannel::GetThrottleQueue(nsIInputChannelThrottleQueue** aQueue) {
6273 NS_ENSURE_ARG_POINTER(aQueue)do { if ((__builtin_expect(!!(!(aQueue)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aQueue" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6273
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
6274 nsCOMPtr<nsIInputChannelThrottleQueue> queue = mThrottleQueue;
6275 queue.forget(aQueue);
6276 return NS_OK;
6277}
6278
6279//------------------------------------------------------------------------------
6280
6281bool HttpBaseChannel::EnsureRequestContextID() {
6282 if (mRequestContextID) {
6283 // Already have a request context ID, no need to do the rest of this work
6284 LOG(("HttpBaseChannel::EnsureRequestContextID this=%p id=%" PRIx64, this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::EnsureRequestContextID this=%p id=%" "l" "x"
, this, mRequestContextID); } } while (0)
6285 mRequestContextID))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::EnsureRequestContextID this=%p id=%" "l" "x"
, this, mRequestContextID); } } while (0)
;
6286 return true;
6287 }
6288
6289 // Find the loadgroup at the end of the chain in order
6290 // to make sure all channels derived from the load group
6291 // use the same connection scope.
6292 if (!mLoadGroup) {
6293 return false;
6294 }
6295
6296 nsCOMPtr<nsILoadGroup> rootLoadGroup;
6297 mLoadGroup->GetRootLoadGroup(getter_AddRefs(rootLoadGroup));
6298 if (!rootLoadGroup) {
6299 return false;
6300 }
6301
6302 // Set the load group connection scope on this channel and its transaction
6303 rootLoadGroup->GetRequestContextID(&mRequestContextID);
6304
6305 LOG(("HttpBaseChannel::EnsureRequestContextID this=%p id=%" PRIx64, this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::EnsureRequestContextID this=%p id=%" "l" "x"
, this, mRequestContextID); } } while (0)
6306 mRequestContextID))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::EnsureRequestContextID this=%p id=%" "l" "x"
, this, mRequestContextID); } } while (0)
;
6307
6308 return true;
6309}
6310
6311bool HttpBaseChannel::EnsureRequestContext() {
6312 if (mRequestContext) {
6313 // Already have a request context, no need to do the rest of this work
6314 return true;
6315 }
6316
6317 if (!EnsureRequestContextID()) {
6318 return false;
6319 }
6320
6321 nsIRequestContextService* rcsvc = gHttpHandler->GetRequestContextService();
6322 if (!rcsvc) {
6323 return false;
6324 }
6325
6326 rcsvc->GetRequestContext(mRequestContextID, getter_AddRefs(mRequestContext));
6327 return static_cast<bool>(mRequestContext);
6328}
6329
6330void HttpBaseChannel::EnsureBrowserId() {
6331 if (mBrowserId) {
6332 return;
6333 }
6334
6335 RefPtr<dom::BrowsingContext> bc;
6336 MOZ_ALWAYS_SUCCEEDS(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))), 1)))
), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6336
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))"
")"); do { MOZ_CrashSequence(__null, 6336); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
6337
6338 if (bc) {
6339 mBrowserId = bc->GetBrowserId();
6340 }
6341}
6342
6343void HttpBaseChannel::SetCorsPreflightParameters(
6344 const nsTArray<nsCString>& aUnsafeHeaders,
6345 bool aShouldStripRequestBodyHeader, bool aShouldStripAuthHeader) {
6346 MOZ_RELEASE_ASSERT(!LoadRequestObserversCalled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadRequestObserversCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadRequestObserversCalled(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadRequestObserversCalled()", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6346); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequestObserversCalled()"
")"); do { MOZ_CrashSequence(__null, 6346); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6347
6348 StoreRequireCORSPreflight(true);
6349 mUnsafeHeaders = aUnsafeHeaders.Clone();
6350 if (aShouldStripRequestBodyHeader || aShouldStripAuthHeader) {
6351 mUnsafeHeaders.RemoveElementsBy([&](const nsCString& aHeader) {
6352 return (aShouldStripRequestBodyHeader &&
6353 (aHeader.LowerCaseEqualsASCII("content-type") ||
6354 aHeader.LowerCaseEqualsASCII("content-encoding") ||
6355 aHeader.LowerCaseEqualsASCII("content-language") ||
6356 aHeader.LowerCaseEqualsASCII("content-location"))) ||
6357 (aShouldStripAuthHeader &&
6358 aHeader.LowerCaseEqualsASCII("authorization"));
6359 });
6360 }
6361}
6362
6363void HttpBaseChannel::SetAltDataForChild(bool aIsForChild) {
6364 StoreAltDataForChild(aIsForChild);
6365}
6366
6367NS_IMETHODIMPnsresult
6368HttpBaseChannel::GetBlockAuthPrompt(bool* aValue) {
6369 if (!aValue) {
6370 return NS_ERROR_FAILURE;
6371 }
6372
6373 *aValue = LoadBlockAuthPrompt();
6374 return NS_OK;
6375}
6376
6377NS_IMETHODIMPnsresult
6378HttpBaseChannel::SetBlockAuthPrompt(bool aValue) {
6379 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6379); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6379, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6379); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6379
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 6379); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
6380
6381 StoreBlockAuthPrompt(aValue);
6382 return NS_OK;
6383}
6384
6385NS_IMETHODIMPnsresult
6386HttpBaseChannel::GetConnectionInfoHashKey(nsACString& aConnectionInfoHashKey) {
6387 if (!mConnectionInfo) {
6388 return NS_ERROR_FAILURE;
6389 }
6390 aConnectionInfoHashKey.Assign(mConnectionInfo->HashKey());
6391 return NS_OK;
6392}
6393
6394NS_IMETHODIMPnsresult
6395HttpBaseChannel::GetLastRedirectFlags(uint32_t* aValue) {
6396 NS_ENSURE_ARG(aValue)do { if ((__builtin_expect(!!(!(aValue)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aValue" ") failed", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6396
); return NS_ERROR_INVALID_ARG; } } while (false)
;
6397 *aValue = mLastRedirectFlags;
6398 return NS_OK;
6399}
6400
6401NS_IMETHODIMPnsresult
6402HttpBaseChannel::SetLastRedirectFlags(uint32_t aValue) {
6403 mLastRedirectFlags = aValue;
6404 return NS_OK;
6405}
6406
6407NS_IMETHODIMPnsresult
6408HttpBaseChannel::GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) {
6409 return NS_ERROR_NOT_IMPLEMENTED;
6410}
6411
6412NS_IMETHODIMPnsresult
6413HttpBaseChannel::SetNavigationStartTimeStamp(TimeStamp aTimeStamp) {
6414 return NS_ERROR_NOT_IMPLEMENTED;
6415}
6416
6417nsresult HttpBaseChannel::CheckRedirectLimit(nsIURI* aNewURI,
6418 uint32_t aRedirectFlags) const {
6419 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
6420 // for internal redirect due to auth retry we do not have any limit
6421 // as we might restrict the number of times a user might retry
6422 // authentication
6423 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_AUTH_RETRY) {
6424 return NS_OK;
6425 }
6426 // Some platform features, like Service Workers, depend on internal
6427 // redirects. We should allow some number of internal redirects above
6428 // and beyond the normal redirect limit so these features continue
6429 // to work.
6430 static const int8_t kMinInternalRedirects = 5;
6431
6432 if (mInternalRedirectCount >= (mRedirectionLimit + kMinInternalRedirects)) {
6433 LOG(("internal redirection limit reached!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "internal redirection limit reached!\n"); } } while (0)
;
6434 return NS_ERROR_REDIRECT_LOOP;
6435 }
6436 return NS_OK;
6437 }
6438
6439 MOZ_ASSERT(aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY
| nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink
::REDIRECT_STS_UPGRADE))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRedirectFlags & (nsIChannelEventSink
::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT
| nsIChannelEventSink::REDIRECT_STS_UPGRADE)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink::REDIRECT_STS_UPGRADE)"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6441
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink::REDIRECT_STS_UPGRADE)"
")"); do { MOZ_CrashSequence(__null, 6441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6440 nsIChannelEventSink::REDIRECT_PERMANENT |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY
| nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink
::REDIRECT_STS_UPGRADE))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRedirectFlags & (nsIChannelEventSink
::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT
| nsIChannelEventSink::REDIRECT_STS_UPGRADE)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink::REDIRECT_STS_UPGRADE)"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6441
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink::REDIRECT_STS_UPGRADE)"
")"); do { MOZ_CrashSequence(__null, 6441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6441 nsIChannelEventSink::REDIRECT_STS_UPGRADE))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY
| nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink
::REDIRECT_STS_UPGRADE))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRedirectFlags & (nsIChannelEventSink
::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT
| nsIChannelEventSink::REDIRECT_STS_UPGRADE)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink::REDIRECT_STS_UPGRADE)"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6441
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink::REDIRECT_STS_UPGRADE)"
")"); do { MOZ_CrashSequence(__null, 6441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6442
6443 if (mRedirectCount >= mRedirectionLimit) {
6444 LOG(("redirection limit reached!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 limit reached!\n"); } } while (0)
;
6445 return NS_ERROR_REDIRECT_LOOP;
6446 }
6447
6448 // in case https-only mode is enabled which upgrades top-level requests to
6449 // https and the page answers with a redirect (meta, 302, win.location, ...)
6450 // then this method can break the cycle which causes the https-only exception
6451 // page to appear. Note that https-first mode breaks upgrade downgrade endless
6452 // loops within ShouldUpgradeHttpsFirstRequest because https-first does not
6453 // display an exception page but needs a soft fallback/downgrade.
6454 if (nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
6455 mURI, aNewURI, mLoadInfo,
6456 {nsHTTPSOnlyUtils::UpgradeDowngradeEndlessLoopOptions::
6457 EnforceForHTTPSOnlyMode})) {
6458 // Mark that we didn't upgrade to https due to loop detection in https-only
6459 // mode to show https-only error page. We know that we are in https-only
6460 // mode, because we passed `EnforceForHTTPSOnlyMode` to
6461 // `IsUpgradeDowngradeEndlessLoop`. In other words we upgrade the request
6462 // with https-only mode, but then immediately cancel the request.
6463 uint32_t httpsOnlyStatus = mLoadInfo->GetHttpsOnlyStatus();
6464 if (httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_UNINITIALIZED) {
6465 httpsOnlyStatus ^= nsILoadInfo::HTTPS_ONLY_UNINITIALIZED;
6466 httpsOnlyStatus |=
6467 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED;
6468 mLoadInfo->SetHttpsOnlyStatus(httpsOnlyStatus);
6469 }
6470
6471 LOG(("upgrade downgrade redirect loop!\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "upgrade downgrade redirect loop!\n"); } } while (0)
;
6472 return NS_ERROR_REDIRECT_LOOP;
6473 }
6474 // in case of http-first mode we want to add an exception to disable the
6475 // upgrade behavior if we have upgrade-downgrade loop to break the loop and
6476 // load the http request next
6477 if (mozilla::StaticPrefs::
6478 dom_security_https_first_add_exception_on_failure() &&
6479 nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
6480 mURI, aNewURI, mLoadInfo,
6481 {nsHTTPSOnlyUtils::UpgradeDowngradeEndlessLoopOptions::
6482 EnforceForHTTPSFirstMode})) {
6483 nsHTTPSOnlyUtils::AddHTTPSFirstException(mURI, mLoadInfo);
6484 }
6485
6486 return NS_OK;
6487}
6488
6489// NOTE: This function duplicates code from nsBaseChannel. This will go away
6490// once HTTP uses nsBaseChannel (part of bug 312760)
6491/* static */
6492void HttpBaseChannel::CallTypeSniffers(void* aClosure, const uint8_t* aData,
6493 uint32_t aCount) {
6494 nsIChannel* chan = static_cast<nsIChannel*>(aClosure);
6495 const char* snifferType = [chan]() {
6496 if (RefPtr<nsHttpChannel> httpChannel = do_QueryObject(chan)) {
6497 switch (httpChannel->GetSnifferCategoryType()) {
6498 case SnifferCategoryType::NetContent:
6499 return NS_CONTENT_SNIFFER_CATEGORY"net-content-sniffers";
6500 case SnifferCategoryType::OpaqueResponseBlocking:
6501 return NS_ORB_SNIFFER_CATEGORY"orb-content-sniffers";
6502 case SnifferCategoryType::All:
6503 return NS_CONTENT_AND_ORB_SNIFFER_CATEGORY"net-and-orb-content-sniffers";
6504 default:
6505 MOZ_ASSERT_UNREACHABLE("Unexpected SnifferCategoryType!")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 SnifferCategoryType!" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected SnifferCategoryType!"
")"); do { MOZ_CrashSequence(__null, 6505); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6506 }
6507 }
6508
6509 return NS_CONTENT_SNIFFER_CATEGORY"net-content-sniffers";
6510 }();
6511
6512 nsAutoCString newType;
6513 NS_SniffContent(snifferType, chan, aData, aCount, newType);
6514 if (!newType.IsEmpty()) {
6515 chan->SetContentType(newType);
6516 }
6517}
6518
6519template <class T>
6520static void ParseServerTimingHeader(
6521 const UniquePtr<T>& aHeader, nsTArray<nsCOMPtr<nsIServerTiming>>& aOutput) {
6522 if (!aHeader) {
6523 return;
6524 }
6525
6526 nsAutoCString serverTimingHeader;
6527 (void)aHeader->GetHeader(nsHttp::Server_Timing, serverTimingHeader);
6528 if (serverTimingHeader.IsEmpty()) {
6529 return;
6530 }
6531
6532 ServerTimingParser parser(serverTimingHeader);
6533 parser.Parse();
6534
6535 nsTArray<nsCOMPtr<nsIServerTiming>> array = parser.TakeServerTimingHeaders();
6536 aOutput.AppendElements(array);
6537}
6538
6539NS_IMETHODIMPnsresult
6540HttpBaseChannel::GetServerTiming(nsIArray** aServerTiming) {
6541 nsresult rv;
6542 NS_ENSURE_ARG_POINTER(aServerTiming)do { if ((__builtin_expect(!!(!(aServerTiming)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aServerTiming" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6542); return NS_ERROR_INVALID_POINTER; } } while (false)
;
6543
6544 nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID"@mozilla.org/array;1", &rv);
6545 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6545); return rv; } } while (false)
;
6546
6547 nsTArray<nsCOMPtr<nsIServerTiming>> data;
6548 rv = GetNativeServerTiming(data);
6549 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6549); return rv; } } while (false)
;
6550
6551 for (const auto& entry : data) {
6552 array->AppendElement(entry);
6553 }
6554
6555 array.forget(aServerTiming);
6556 return NS_OK;
6557}
6558
6559NS_IMETHODIMPnsresult
6560HttpBaseChannel::GetNativeServerTiming(
6561 nsTArray<nsCOMPtr<nsIServerTiming>>& aServerTiming) {
6562 aServerTiming.Clear();
6563
6564 if (nsContentUtils::ComputeIsSecureContext(this)) {
6565 ParseServerTimingHeader(mResponseHead, aServerTiming);
6566 ParseServerTimingHeader(mResponseTrailers, aServerTiming);
6567 }
6568
6569 return NS_OK;
6570}
6571
6572NS_IMETHODIMPnsresult
6573HttpBaseChannel::CancelByURLClassifier(nsresult aErrorCode) {
6574 MOZ_ASSERT(ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ChannelClassifierUtils::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(ChannelClassifierUtils::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6574
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 6574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6575 return Cancel(aErrorCode);
6576}
6577
6578NS_IMETHODIMPnsresult HttpBaseChannel::SetIPv4Disabled() {
6579 mCaps |= NS_HTTP_DISABLE_IPV4(1 << 17);
6580 return NS_OK;
6581}
6582
6583NS_IMETHODIMPnsresult HttpBaseChannel::SetIPv6Disabled() {
6584 mCaps |= NS_HTTP_DISABLE_IPV6(1 << 18);
6585 return NS_OK;
6586}
6587
6588NS_IMETHODIMPnsresult HttpBaseChannel::GetResponseEmbedderPolicy(
6589 bool aIsOriginTrialCoepCredentiallessEnabled,
6590 nsILoadInfo::CrossOriginEmbedderPolicy* aOutPolicy) {
6591 *aOutPolicy = nsILoadInfo::EMBEDDER_POLICY_NULL;
6592 if (!mResponseHead) {
6593 return NS_ERROR_NOT_AVAILABLE;
6594 }
6595
6596 if (!nsContentUtils::ComputeIsSecureContext(this)) {
6597 // Feature is only available for secure contexts.
6598 return NS_OK;
6599 }
6600
6601 nsAutoCString content;
6602 (void)mResponseHead->GetHeader(nsHttp::Cross_Origin_Embedder_Policy, content);
6603 *aOutPolicy = NS_GetCrossOriginEmbedderPolicyFromHeader(
6604 content, aIsOriginTrialCoepCredentiallessEnabled);
6605 return NS_OK;
6606}
6607
6608// Obtain a cross-origin opener-policy from a response response and a
6609// cross-origin opener policy initiator.
6610// https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
6611NS_IMETHODIMPnsresult HttpBaseChannel::ComputeCrossOriginOpenerPolicy(
6612 nsILoadInfo::CrossOriginOpenerPolicy aInitiatorPolicy,
6613 nsILoadInfo::CrossOriginOpenerPolicy* aOutPolicy) {
6614 MOZ_ASSERT(aOutPolicy)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOutPolicy)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOutPolicy))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aOutPolicy", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6614); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutPolicy"
")"); do { MOZ_CrashSequence(__null, 6614); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6615 *aOutPolicy = nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
6616
6617 if (!mResponseHead) {
6618 return NS_ERROR_NOT_AVAILABLE;
6619 }
6620
6621 // COOP headers are ignored for insecure-context loads.
6622 if (!nsContentUtils::ComputeIsSecureContext(this)) {
6623 return NS_OK;
6624 }
6625
6626 nsAutoCString openerPolicy;
6627 (void)mResponseHead->GetHeader(nsHttp::Cross_Origin_Opener_Policy,
6628 openerPolicy);
6629
6630 // Cross-Origin-Opener-Policy = %s"same-origin" /
6631 // %s"same-origin-allow-popups" /
6632 // %s"unsafe-none"; case-sensitive
6633
6634 nsresult rv = SFV::ParseItem<SFV::Token>(openerPolicy, openerPolicy);
6635 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6636 return rv;
6637 }
6638
6639 nsILoadInfo::CrossOriginOpenerPolicy policy =
6640 nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
6641
6642 if (openerPolicy.EqualsLiteral("same-origin")) {
6643 policy = nsILoadInfo::OPENER_POLICY_SAME_ORIGIN;
6644 } else if (openerPolicy.EqualsLiteral("same-origin-allow-popups")) {
6645 policy = nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_ALLOW_POPUPS;
6646 }
6647 if (policy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN) {
6648 nsILoadInfo::CrossOriginEmbedderPolicy coep =
6649 nsILoadInfo::EMBEDDER_POLICY_NULL;
6650 bool isCoepCredentiallessEnabled;
6651 rv = mLoadInfo->GetIsOriginTrialCoepCredentiallessEnabledForTopLevel(
6652 &isCoepCredentiallessEnabled);
6653 if (!isCoepCredentiallessEnabled) {
6654 nsAutoCString originTrialToken;
6655 (void)mResponseHead->GetHeader(nsHttp::OriginTrial, originTrialToken);
6656 if (!originTrialToken.IsEmpty()) {
6657 nsCOMPtr<nsIPrincipal> resultPrincipal;
6658 rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
6659 this, getter_AddRefs(resultPrincipal));
6660 if (!NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6660)
) {
6661 OriginTrials trials;
6662 trials.UpdateFromToken(NS_ConvertASCIItoUTF16(originTrialToken),
6663 resultPrincipal);
6664 if (trials.IsEnabled(OriginTrial::CoepCredentialless)) {
6665 isCoepCredentiallessEnabled = true;
6666 }
6667 }
6668 }
6669 }
6670
6671 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6671); return rv; } } while (false)
;
6672 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetResponseEmbedderPolicy
(isCoepCredentiallessEnabled, &coep))), 1)))
6673 GetResponseEmbedderPolicy(isCoepCredentiallessEnabled, &coep))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetResponseEmbedderPolicy
(isCoepCredentiallessEnabled, &coep))), 1)))
&&
6674 (coep == nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP ||
6675 coep == nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS)) {
6676 policy =
6677 nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP;
6678 }
6679 }
6680
6681 *aOutPolicy = policy;
6682 return NS_OK;
6683}
6684
6685NS_IMETHODIMPnsresult
6686HttpBaseChannel::GetCrossOriginOpenerPolicy(
6687 nsILoadInfo::CrossOriginOpenerPolicy* aPolicy) {
6688 MOZ_ASSERT(aPolicy)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPolicy)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPolicy))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aPolicy", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPolicy" ")"
); do { MOZ_CrashSequence(__null, 6688); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6689 if (!aPolicy) {
6690 return NS_ERROR_INVALID_ARG;
6691 }
6692 // If this method is called before OnStartRequest (ie. before we call
6693 // ComputeCrossOriginOpenerPolicy) or if we were unable to compute the
6694 // policy we'll throw an error.
6695 if (!LoadOnStartRequestCalled()) {
6696 return NS_ERROR_NOT_AVAILABLE;
6697 }
6698 *aPolicy = mComputedCrossOriginOpenerPolicy;
6699 return NS_OK;
6700}
6701
6702NS_IMETHODIMPnsresult
6703HttpBaseChannel::HasCrossOriginOpenerPolicyMismatch(bool* aIsMismatch) {
6704 // This should only be called in parent process.
6705 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6705
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 6705); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6706 *aIsMismatch = LoadHasCrossOriginOpenerPolicyMismatch();
6707 return NS_OK;
6708}
6709
6710NS_IMETHODIMPnsresult
6711HttpBaseChannel::GetOriginAgentClusterHeader(bool* aValue) {
6712 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 6712
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 6712); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6713 if (!mResponseHead) {
6714 return NS_ERROR_NOT_AVAILABLE;
6715 }
6716
6717 nsAutoCString content;
6718 nsresult rv = mResponseHead->GetHeader(nsHttp::OriginAgentCluster, content);
6719 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6720 return rv;
6721 }
6722
6723 // Origin-Agent-Cluster = <boolean>
6724 return SFV::ParseItem<SFV::SFVBool>(content, *aValue);
6725}
6726
6727void HttpBaseChannel::MaybeFlushConsoleReports() {
6728 // Flush if we have a known window ID.
6729 if (mLoadInfo->GetInnerWindowID() > 0) {
6730 FlushReportsToConsole(mLoadInfo->GetInnerWindowID());
6731 return;
6732 }
6733
6734 // If this channel is part of a loadGroup, we can flush the console reports
6735 // immediately.
6736 nsCOMPtr<nsILoadGroup> loadGroup;
6737 nsresult rv = GetLoadGroup(getter_AddRefs(loadGroup));
6738 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && loadGroup) {
6739 FlushConsoleReports(loadGroup);
6740 }
6741}
6742
6743void HttpBaseChannel::DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() {}
6744
6745bool HttpBaseChannel::Http3Allowed() const {
6746 bool allowedProxyInfo =
6747 mProxyInfo ? (static_cast<nsProxyInfo*>(mProxyInfo.get())->IsDirect() ||
6748 static_cast<nsProxyInfo*>(mProxyInfo.get())->IsHttp3Proxy())
6749 : true;
6750 // TODO: When mUpgradeProtocolCallback is not null, we should allow HTTP/3 for
6751 // connect-udp.
6752 return !mUpgradeProtocolCallback && allowedProxyInfo &&
6753 !(mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) && !LoadBeConservative() &&
6754 LoadAllowHttp3();
6755}
6756
6757UniquePtr<nsHttpResponseHead>
6758HttpBaseChannel::MaybeCloneResponseHeadForCachedResource() {
6759 if (!mResponseHead) {
6760 return nullptr;
6761 }
6762
6763 return MakeUnique<nsHttpResponseHead>(*mResponseHead);
6764}
6765
6766void HttpBaseChannel::SetDummyChannelForCachedResource(
6767 const nsHttpResponseHead* aMaybeResponseHead /* = nullptr */) {
6768 mDummyChannelForCachedResource = true;
6769 MOZ_ASSERT(!mResponseHead,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mResponseHead)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mResponseHead))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mResponseHead"
" (" "SetDummyChannelForCachedResource should only be called once"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mResponseHead"
") (" "SetDummyChannelForCachedResource should only be called once"
")"); do { MOZ_CrashSequence(__null, 6770); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6770 "SetDummyChannelForCachedResource should only be called once")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mResponseHead)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mResponseHead))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mResponseHead"
" (" "SetDummyChannelForCachedResource should only be called once"
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mResponseHead"
") (" "SetDummyChannelForCachedResource should only be called once"
")"); do { MOZ_CrashSequence(__null, 6770); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6771 if (aMaybeResponseHead) {
6772 mResponseHead = MakeUnique<nsHttpResponseHead>(*aMaybeResponseHead);
6773 } else {
6774 mResponseHead = MakeUnique<nsHttpResponseHead>();
6775 }
6776}
6777
6778void HttpBaseChannel::SetEarlyHints(
6779 nsTArray<EarlyHintConnectArgs>&& aEarlyHints) {
6780 mEarlyHints = std::move(aEarlyHints);
6781}
6782
6783nsTArray<EarlyHintConnectArgs>&& HttpBaseChannel::TakeEarlyHints() {
6784 return std::move(mEarlyHints);
6785}
6786
6787NS_IMETHODIMPnsresult
6788HttpBaseChannel::SetEarlyHintPreloaderId(uint64_t aEarlyHintPreloaderId) {
6789 mEarlyHintPreloaderId = aEarlyHintPreloaderId;
6790 return NS_OK;
6791}
6792
6793NS_IMETHODIMPnsresult
6794HttpBaseChannel::GetEarlyHintPreloaderId(uint64_t* aEarlyHintPreloaderId) {
6795 NS_ENSURE_ARG_POINTER(aEarlyHintPreloaderId)do { if ((__builtin_expect(!!(!(aEarlyHintPreloaderId)), 0)))
{ NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEarlyHintPreloaderId"
") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6795); return NS_ERROR_INVALID_POINTER; } } while (false)
;
6796 *aEarlyHintPreloaderId = mEarlyHintPreloaderId;
6797 return NS_OK;
6798}
6799
6800NS_IMETHODIMPnsresult
6801HttpBaseChannel::SetClassicScriptHintCharset(
6802 const nsAString& aClassicScriptHintCharset) {
6803 mClassicScriptHintCharset = aClassicScriptHintCharset;
6804 return NS_OK;
6805}
6806
6807NS_IMETHODIMPnsresult HttpBaseChannel::GetClassicScriptHintCharset(
6808 nsAString& aClassicScriptHintCharset) {
6809 aClassicScriptHintCharset = mClassicScriptHintCharset;
6810 return NS_OK;
6811}
6812
6813NS_IMETHODIMPnsresult HttpBaseChannel::SetDocumentCharacterSet(
6814 const nsAString& aDocumentCharacterSet) {
6815 mDocumentCharacterSet = aDocumentCharacterSet;
6816 return NS_OK;
6817}
6818
6819NS_IMETHODIMPnsresult HttpBaseChannel::GetDocumentCharacterSet(
6820 nsAString& aDocumentCharacterSet) {
6821 aDocumentCharacterSet = mDocumentCharacterSet;
6822 return NS_OK;
6823}
6824
6825void HttpBaseChannel::SetConnectionInfo(nsHttpConnectionInfo* aCI) {
6826 mConnectionInfo = aCI;
6827}
6828
6829NS_IMETHODIMPnsresult
6830HttpBaseChannel::GetIsProxyUsed(bool* aIsProxyUsed) {
6831 if (mProxyInfo) {
6832 if (!static_cast<nsProxyInfo*>(mProxyInfo.get())->IsDirect()) {
6833 StoreIsProxyUsed(true);
6834 }
6835 }
6836 *aIsProxyUsed = LoadIsProxyUsed();
6837 return NS_OK;
6838}
6839
6840static void CollectORBBlockTelemetry(
6841 const OpaqueResponseBlockedTelemetryReason aTelemetryReason,
6842 ExtContentPolicy aPolicy) {
6843 glean::orb::block_reason.EnumGet(aTelemetryReason).Add();
6844
6845 switch (aPolicy) {
6846 case ExtContentPolicy::TYPE_INVALID:
6847 glean::orb::block_initiator
6848 .EnumGet(glean::orb::BlockInitiatorLabel::eInvalid)
6849 .Add();
6850 break;
6851 case ExtContentPolicy::TYPE_OTHER:
6852 glean::orb::block_initiator
6853 .EnumGet(glean::orb::BlockInitiatorLabel::eOther)
6854 .Add();
6855 break;
6856 case ExtContentPolicy::TYPE_FETCH:
6857 glean::orb::block_initiator
6858 .EnumGet(glean::orb::BlockInitiatorLabel::eBlockedFetch)
6859 .Add();
6860 break;
6861 case ExtContentPolicy::TYPE_SCRIPT:
6862 glean::orb::block_initiator
6863 .EnumGet(glean::orb::BlockInitiatorLabel::eScript)
6864 .Add();
6865 break;
6866 case ExtContentPolicy::TYPE_JSON:
6867 glean::orb::block_initiator
6868 .EnumGet(glean::orb::BlockInitiatorLabel::eJson)
6869 .Add();
6870 break;
6871 case ExtContentPolicy::TYPE_IMAGE:
6872 glean::orb::block_initiator
6873 .EnumGet(glean::orb::BlockInitiatorLabel::eImage)
6874 .Add();
6875 break;
6876 case ExtContentPolicy::TYPE_STYLESHEET:
6877 glean::orb::block_initiator
6878 .EnumGet(glean::orb::BlockInitiatorLabel::eStylesheet)
6879 .Add();
6880 break;
6881 case ExtContentPolicy::TYPE_XMLHTTPREQUEST:
6882 glean::orb::block_initiator
6883 .EnumGet(glean::orb::BlockInitiatorLabel::eXmlhttprequest)
6884 .Add();
6885 break;
6886 case ExtContentPolicy::TYPE_DTD:
6887 glean::orb::block_initiator.EnumGet(glean::orb::BlockInitiatorLabel::eDtd)
6888 .Add();
6889 break;
6890 case ExtContentPolicy::TYPE_FONT:
6891 glean::orb::block_initiator
6892 .EnumGet(glean::orb::BlockInitiatorLabel::eFont)
6893 .Add();
6894 break;
6895 case ExtContentPolicy::TYPE_MEDIA:
6896 glean::orb::block_initiator
6897 .EnumGet(glean::orb::BlockInitiatorLabel::eMedia)
6898 .Add();
6899 break;
6900 case ExtContentPolicy::TYPE_CSP_REPORT:
6901 glean::orb::block_initiator
6902 .EnumGet(glean::orb::BlockInitiatorLabel::eCspReport)
6903 .Add();
6904 break;
6905 case ExtContentPolicy::TYPE_XSLT:
6906 glean::orb::block_initiator
6907 .EnumGet(glean::orb::BlockInitiatorLabel::eXslt)
6908 .Add();
6909 break;
6910 case ExtContentPolicy::TYPE_IMAGESET:
6911 glean::orb::block_initiator
6912 .EnumGet(glean::orb::BlockInitiatorLabel::eImageset)
6913 .Add();
6914 break;
6915 case ExtContentPolicy::TYPE_WEB_MANIFEST:
6916 glean::orb::block_initiator
6917 .EnumGet(glean::orb::BlockInitiatorLabel::eWebManifest)
6918 .Add();
6919 break;
6920 case ExtContentPolicy::TYPE_SPECULATIVE:
6921 glean::orb::block_initiator
6922 .EnumGet(glean::orb::BlockInitiatorLabel::eSpeculative)
6923 .Add();
6924 break;
6925 case ExtContentPolicy::TYPE_UA_FONT:
6926 glean::orb::block_initiator
6927 .EnumGet(glean::orb::BlockInitiatorLabel::eUaFont)
6928 .Add();
6929 break;
6930 case ExtContentPolicy::TYPE_PROXIED_WEBRTC_MEDIA:
6931 glean::orb::block_initiator
6932 .EnumGet(glean::orb::BlockInitiatorLabel::eProxiedWebrtcMedia)
6933 .Add();
6934 break;
6935 case ExtContentPolicy::TYPE_PING:
6936 glean::orb::block_initiator
6937 .EnumGet(glean::orb::BlockInitiatorLabel::ePing)
6938 .Add();
6939 break;
6940 case ExtContentPolicy::TYPE_BEACON:
6941 glean::orb::block_initiator
6942 .EnumGet(glean::orb::BlockInitiatorLabel::eBeacon)
6943 .Add();
6944 break;
6945 case ExtContentPolicy::TYPE_WEB_TRANSPORT:
6946 glean::orb::block_initiator
6947 .EnumGet(glean::orb::BlockInitiatorLabel::eWebTransport)
6948 .Add();
6949 break;
6950 case ExtContentPolicy::TYPE_WEB_IDENTITY:
6951 // Don't bother extending the telemetry for this.
6952 glean::orb::block_initiator
6953 .EnumGet(glean::orb::BlockInitiatorLabel::eOther)
6954 .Add();
6955 break;
6956 case ExtContentPolicy::TYPE_TEXT:
6957 glean::orb::block_initiator
6958 .EnumGet(glean::orb::BlockInitiatorLabel::eText)
6959 .Add();
6960 break;
6961 case ExtContentPolicy::TYPE_DOCUMENT:
6962 case ExtContentPolicy::TYPE_SUBDOCUMENT:
6963 case ExtContentPolicy::TYPE_OBJECT:
6964 case ExtContentPolicy::TYPE_WEBSOCKET:
6965 case ExtContentPolicy::TYPE_SAVEAS_DOWNLOAD:
6966 MOZ_ASSERT_UNREACHABLE("Shouldn't block this type")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: "
"Shouldn't block this type" ")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6966); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Shouldn't block this type" ")");
do { MOZ_CrashSequence(__null, 6966); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6967 // DOCUMENT, SUBDOCUMENT, OBJECT,
6968 // WEBSOCKET and SAVEAS_DOWNLOAD are excluded from ORB
6969 glean::orb::block_initiator
6970 .EnumGet(glean::orb::BlockInitiatorLabel::eExcluded)
6971 .Add();
6972 break;
6973 // Do not add default: so that compilers can catch the missing case.
6974 }
6975}
6976
6977void HttpBaseChannel::LogORBError(
6978 const nsAString& aReason,
6979 const OpaqueResponseBlockedTelemetryReason aTelemetryReason) {
6980 auto policy = mLoadInfo->GetExternalContentPolicyType();
6981 CollectORBBlockTelemetry(aTelemetryReason, policy);
6982
6983 // Blocking `ExtContentPolicy::TYPE_BEACON` isn't web observable, so keep
6984 // quiet in the console about blocking it.
6985 if (policy == ExtContentPolicy::TYPE_BEACON) {
6986 return;
6987 }
6988
6989 RefPtr<dom::Document> doc;
6990 mLoadInfo->GetLoadingDocument(getter_AddRefs(doc));
6991
6992 nsAutoCString uri;
6993 if (mURI->SchemeIs("data")) {
6994 uri.AssignLiteral("data:...");
6995 } else {
6996 nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(mURI);
6997 exposableURI->GetSpec(uri);
6998 }
6999
7000 uint64_t contentWindowId;
7001 GetTopLevelContentWindowId(&contentWindowId);
7002 if (contentWindowId) {
7003 nsContentUtils::ReportToConsoleByWindowID(
7004 u"A resource is blocked by OpaqueResponseBlocking, please check browser console for details."_ns,
7005 nsIScriptError::warningFlag, "ORB"_ns, contentWindowId,
7006 SourceLocation(mURI.get()));
7007 }
7008
7009 AutoTArray<nsString, 2> params;
7010 params.AppendElement(NS_ConvertUTF8toUTF16(uri));
7011 params.AppendElement(aReason);
7012 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "ORB"_ns, doc,
7013 PropertiesFile::NECKO_PROPERTIES,
7014 "ResourceBlockedORB", params);
7015}
7016
7017NS_IMETHODIMPnsresult HttpBaseChannel::SetEarlyHintLinkType(
7018 uint32_t aEarlyHintLinkType) {
7019 mEarlyHintLinkType = aEarlyHintLinkType;
7020 return NS_OK;
7021}
7022
7023NS_IMETHODIMPnsresult HttpBaseChannel::GetEarlyHintLinkType(
7024 uint32_t* aEarlyHintLinkType) {
7025 *aEarlyHintLinkType = mEarlyHintLinkType;
7026 return NS_OK;
7027}
7028
7029NS_IMETHODIMPnsresult
7030HttpBaseChannel::SetHasContentDecompressed(bool aValue) {
7031 LOG(("HttpBaseChannel::SetHasContentDecompressed [this=%p value=%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
, "HttpBaseChannel::SetHasContentDecompressed [this=%p value=%d]\n"
, this, aValue); } } while (0)
7032 aValue))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "HttpBaseChannel::SetHasContentDecompressed [this=%p value=%d]\n"
, this, aValue); } } while (0)
;
7033 mHasContentDecompressed = aValue;
7034 return NS_OK;
7035}
7036NS_IMETHODIMPnsresult
7037HttpBaseChannel::GetHasContentDecompressed(bool* value) {
7038 *value = mHasContentDecompressed;
7039 return NS_OK;
7040}
7041
7042NS_IMETHODIMPnsresult
7043HttpBaseChannel::SetRenderBlocking(bool aRenderBlocking) {
7044 mRenderBlocking = aRenderBlocking;
7045 return NS_OK;
7046}
7047
7048NS_IMETHODIMPnsresult
7049HttpBaseChannel::GetRenderBlocking(bool* aRenderBlocking) {
7050 *aRenderBlocking = mRenderBlocking;
7051 return NS_OK;
7052}
7053
7054NS_IMETHODIMPnsresult HttpBaseChannel::GetLastTransportStatus(
7055 nsresult* aLastTransportStatus) {
7056 return NS_ERROR_NOT_IMPLEMENTED;
7057}
7058
7059void HttpBaseChannel::SetFetchPriorityDOM(
7060 mozilla::dom::FetchPriority aPriority) {
7061 switch (aPriority) {
7062 case mozilla::dom::FetchPriority::Auto:
7063 SetFetchPriority(nsIClassOfService::FETCHPRIORITY_AUTO);
7064 return;
7065 case mozilla::dom::FetchPriority::High:
7066 SetFetchPriority(nsIClassOfService::FETCHPRIORITY_HIGH);
7067 return;
7068 case mozilla::dom::FetchPriority::Low:
7069 SetFetchPriority(nsIClassOfService::FETCHPRIORITY_LOW);
7070 return;
7071 default:
7072 MOZ_ASSERT_UNREACHABLE()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: "
")", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 7072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " ")"); do { MOZ_CrashSequence(__null
, 7072); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
7073 }
7074}
7075
7076} // namespace net
7077} // namespace mozilla
7078#undef LOGORB