Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http/./../../../../netwerk/protocol/http/HttpBaseChannel.cpp
Warning:line 1661, column 5
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/dom/base -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/cookie -I /root/firefox-clang/netwerk/dns -I /root/firefox-clang/netwerk/ipc -I /root/firefox-clang/netwerk/socket/neqo_glue -I /root/firefox-clang/netwerk/url-classifier -I /root/firefox-clang/extensions/auth -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c++ Unified_cpp_protocol_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 <memory>
10#include <utility>
11
12#include "HttpBaseChannel.h"
13#include "HttpLog.h"
14#include "LoadInfo.h"
15#include "ReferrerInfo.h"
16#include "mozIRemoteLazyInputStream.h"
17#include "mozIThirdPartyUtil.h"
18#include "mozilla/AntiTrackingUtils.h"
19#include "mozilla/BasePrincipal.h"
20#include "mozilla/BinarySearch.h"
21#include "mozilla/CompactPair.h"
22#include "mozilla/Components.h"
23#include "mozilla/ConsoleReportCollector.h"
24#include "mozilla/DebugOnly.h"
25#include "mozilla/InputStreamLengthHelper.h"
26#include "mozilla/LoadInfo.h"
27#include "mozilla/MathAlgorithms.h"
28#include "mozilla/Mutex.h"
29#include "mozilla/NullPrincipal.h"
30#include "mozilla/PermissionManager.h"
31#include "mozilla/RemoteLazyInputStreamChild.h"
32#include "mozilla/StaticPrefs_browser.h"
33#include "mozilla/StaticPrefs_fission.h"
34#include "mozilla/StaticPrefs_javascript.h"
35#include "mozilla/StaticPrefs_network.h"
36#include "mozilla/StaticPrefs_security.h"
37#include "mozilla/Telemetry.h"
38#include "mozilla/Tokenizer.h"
39#include "mozilla/browser/NimbusFeatures.h"
40#include "mozilla/dom/BrowsingContext.h"
41#include "mozilla/dom/CanonicalBrowsingContext.h"
42#include "mozilla/dom/ContentChild.h"
43#include "mozilla/dom/Document.h"
44#include "mozilla/dom/FetchPriority.h"
45#include "mozilla/dom/LoadURIOptionsBinding.h"
46#include "mozilla/dom/ParentProcessChannelHandle.h"
47#include "mozilla/dom/Performance.h"
48#include "mozilla/dom/PerformanceStorage.h"
49#include "mozilla/dom/PolicyContainer.h"
50#include "mozilla/dom/ProcessIsolation.h"
51#include "mozilla/dom/RequestBinding.h"
52#include "mozilla/dom/WindowGlobalParent.h"
53#include "mozilla/dom/nsHTTPSOnlyUtils.h"
54#include "mozilla/dom/nsMixedContentBlocker.h"
55#include "mozilla/glean/NetwerkProtocolHttpMetrics.h"
56#include "mozilla/net/ChannelClassifierUtils.h"
57#include "mozilla/net/OpaqueResponseUtils.h"
58#include "mozilla/net/SFV.h"
59#include "nsBufferedStreams.h"
60#include "nsCOMPtr.h"
61#include "nsCRT.h"
62#include "nsContentSecurityManager.h"
63#include "nsContentSecurityUtils.h"
64#include "nsContentUtils.h"
65#include "nsDebug.h"
66#include "nsEscape.h"
67#include "nsGlobalWindowInner.h"
68#include "nsGlobalWindowOuter.h"
69#include "nsHTTPCompressConv.h"
70#include "nsHttpChannel.h"
71#include "nsHttpHandler.h"
72#include "nsICacheInfoChannel.h"
73#include "nsICachingChannel.h"
74#include "nsIChannelEventSink.h"
75#include "nsIConsoleService.h"
76#include "nsIContentPolicy.h"
77#include "nsICookieService.h"
78#include "nsIDNSService.h"
79#include "nsIDOMWindowUtils.h"
80#include "nsIDocShell.h"
81#include "nsIEncodedChannel.h"
82#include "nsIHttpHeaderVisitor.h"
83#include "nsIMIMEInputStream.h"
84#include "nsIMultiplexInputStream.h"
85#include "nsIMutableArray.h"
86#include "nsINetworkInterceptController.h"
87#include "nsIOService.h"
88#include "nsIObserverService.h"
89#include "nsIPrincipal.h"
90#include "nsIProtocolProxyService.h"
91#include "nsIScriptError.h"
92#include "nsIScriptSecurityManager.h"
93#include "nsISecurityConsoleMessage.h"
94#include "nsISeekableStream.h"
95#include "nsIStorageStream.h"
96#include "nsIStreamConverterService.h"
97#include "nsITimedChannel.h"
98#include "nsITransportSecurityInfo.h"
99#include "nsIURIMutator.h"
100#include "nsMimeTypes.h"
101#include "nsNetCID.h"
102#include "nsNetUtil.h"
103#include "nsPIDOMWindow.h"
104#include "nsProxyRelease.h"
105#include "nsQueryObject.h"
106#include "nsReadableUtils.h"
107#include "nsRedirectHistoryEntry.h"
108#include "nsServerTiming.h"
109#include "nsStreamListenerWrapper.h"
110#include "nsStreamUtils.h"
111#include "nsString.h"
112#include "nsThreadUtils.h"
113#include "nsURLHelper.h"
114
115using mozilla::dom::ForceMediaDocument;
116using mozilla::dom::RequestMode;
117
118#define LOGORB(msg, ...) \
119 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)
120 ("%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)
121
122namespace mozilla {
123namespace net {
124
125static bool IsHeaderBlacklistedForRedirectCopy(nsHttpAtom const& aHeader) {
126 // IMPORTANT: keep this list ASCII-code sorted
127 static nsHttpAtomLiteral const* blackList[] = {
128 &nsHttp::Accept,
129 &nsHttp::Accept_Encoding,
130 &nsHttp::Accept_Language,
131 &nsHttp::Alternate_Service_Used,
132 &nsHttp::Authentication,
133 &nsHttp::Authorization,
134 &nsHttp::Connection,
135 &nsHttp::Content_Length,
136 &nsHttp::Cookie,
137 &nsHttp::Host,
138 &nsHttp::If,
139 &nsHttp::If_Match,
140 &nsHttp::If_Modified_Since,
141 &nsHttp::If_None_Match,
142 &nsHttp::If_None_Match_Any,
143 &nsHttp::If_Range,
144 &nsHttp::If_Unmodified_Since,
145 &nsHttp::Proxy_Authenticate,
146 &nsHttp::Proxy_Authorization,
147 &nsHttp::Range,
148 &nsHttp::TE,
149 &nsHttp::Transfer_Encoding,
150 &nsHttp::Upgrade,
151 &nsHttp::User_Agent,
152 &nsHttp::WWW_Authenticate};
153
154 class HttpAtomComparator {
155 nsHttpAtom const& mTarget;
156
157 public:
158 explicit HttpAtomComparator(nsHttpAtom const& aTarget) : mTarget(aTarget) {}
159 int operator()(nsHttpAtom const* aVal) const {
160 if (mTarget == *aVal) {
161 return 0;
162 }
163 return strcmp(mTarget.get(), aVal->get());
164 }
165 int operator()(nsHttpAtomLiteral const* aVal) const {
166 if (mTarget == *aVal) {
167 return 0;
168 }
169 return strcmp(mTarget.get(), aVal->get());
170 }
171 };
172
173 size_t unused;
174 return BinarySearchIf(blackList, 0, std::size(blackList),
175 HttpAtomComparator(aHeader), &unused);
176}
177
178class AddHeadersToChannelVisitor final : public nsIHttpHeaderVisitor {
179 public:
180 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:
181
182 explicit AddHeadersToChannelVisitor(nsIHttpChannel* aChannel)
183 : mChannel(aChannel) {}
184
185 NS_IMETHODvirtual nsresult VisitHeader(const nsACString& aHeader,
186 const nsACString& aValue) override {
187 nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
188 if (!IsHeaderBlacklistedForRedirectCopy(atom)) {
189 DebugOnly<nsresult> rv =
190 mChannel->SetRequestHeader(aHeader, aValue, false);
191 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"
, 191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 191); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
192 }
193 return NS_OK;
194 }
195
196 private:
197 ~AddHeadersToChannelVisitor() = default;
198
199 nsCOMPtr<nsIHttpChannel> mChannel;
200};
201
202NS_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"
, 202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 202
); __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"
, 202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"AddHeadersToChannelVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 202); __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"
, 202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 202
); __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"
, 202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"AddHeadersToChannelVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 202); __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"
, 202); 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; }
203
204static OpaqueResponseFilterFetch ConfiguredFilterFetchResponseBehaviour() {
205 uint32_t pref = StaticPrefs::
206 browser_opaqueResponseBlocking_filterFetchResponse_DoNotUseDirectly();
207 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", 208
)
208 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", 208
)
) {
209 return OpaqueResponseFilterFetch::All;
210 }
211
212 return static_cast<OpaqueResponseFilterFetch>(pref);
213}
214
215HttpBaseChannel::HttpBaseChannel()
216 : mReportCollector(new ConsoleReportCollector()),
217 mHttpHandler(gHttpHandler),
218 mClassOfService(0, false),
219 mRequestMode(RequestMode::No_cors),
220 mRedirectionLimit(gHttpHandler->RedirectionLimit()),
221 mCachedOpaqueResponseBlockingPref(
222 StaticPrefs::browser_opaqueResponseBlocking()) {
223 StoreApplyConversion(true);
224 StoreAllowSTS(true);
225 StoreTracingEnabled(true);
226 StoreReportTiming(true);
227 StoreAllowSpdy(true);
228 StoreAllowHttp3(true);
229 StoreAllowAltSvc(true);
230 StoreResponseTimeoutEnabled(true);
231 StoreAllRedirectsSameOrigin(true);
232 StoreAllRedirectsSameOriginIgnoringInternal(true);
233 StoreAllRedirectsPassTimingAllowCheck(true);
234 StoreUpgradableToSecure(true);
235 StoreIsUserAgentHeaderModified(false);
236
237 this->mSelfAddr.inet = {};
238 this->mPeerAddr.inet = {};
239 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)
;
240
241 // Subfields of unions cannot be targeted in an initializer list.
242#ifdef MOZ_VALGRIND
243 // Zero the entire unions so that Valgrind doesn't complain when we send them
244 // to another process.
245 memset(&mSelfAddr, 0, sizeof(NetAddr));
246 memset(&mPeerAddr, 0, sizeof(NetAddr));
247#endif
248 mSelfAddr.raw.family = PR_AF_UNSPEC0;
249 mPeerAddr.raw.family = PR_AF_UNSPEC0;
250}
251
252HttpBaseChannel::~HttpBaseChannel() {
253 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)
;
254
255 // Make sure we don't leak
256 CleanRedirectCacheChainIfNecessary();
257
258 ReleaseMainThreadOnlyReferences();
259}
260
261namespace { // anon
262
263class NonTailRemover : public nsISupports {
264 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:
265
266 explicit NonTailRemover(nsIRequestContext* rc) : mRequestContext(rc) {}
267
268 private:
269 virtual ~NonTailRemover() {
270 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", 270
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 270); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
271 mRequestContext->RemoveNonTailRequest();
272 }
273
274 nsCOMPtr<nsIRequestContext> mRequestContext;
275};
276
277NS_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"
, 277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 277
); __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"
, 277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"NonTailRemover\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 277); __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"
, 277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 277
); __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"
, 277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"NonTailRemover\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 277); __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"
, 277); 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; }
278
279} // namespace
280
281void HttpBaseChannel::ReleaseMainThreadOnlyReferences() {
282 if (NS_IsMainThread()) {
283 // Already on main thread, let dtor to
284 // take care of releasing references
285 RemoveAsNonTailRequest();
286 return;
287 }
288
289 nsTArray<nsCOMPtr<nsISupports>> arrayToRelease;
290 arrayToRelease.AppendElement(mLoadGroup.forget());
291 arrayToRelease.AppendElement(mLoadInfo.forget());
292 arrayToRelease.AppendElement(mCallbacks.forget());
293 arrayToRelease.AppendElement(mProgressSink.forget());
294 arrayToRelease.AppendElement(mPrincipal.forget());
295 arrayToRelease.AppendElement(mListener.forget());
296 arrayToRelease.AppendElement(mCompressListener.forget());
297 arrayToRelease.AppendElement(mORB.forget());
298
299 if (LoadAddedAsNonTailRequest()) {
300 // RemoveNonTailRequest() on our request context must be called on the main
301 // thread
302 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"
, 303); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mRequestContext"
") (" "Someone released rc or set flags w/o having it?" ")")
; do { MOZ_CrashSequence(__null, 303); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
303 "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"
, 303); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mRequestContext"
") (" "Someone released rc or set flags w/o having it?" ")")
; do { MOZ_CrashSequence(__null, 303); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
304
305 nsCOMPtr<nsISupports> nonTailRemover(new NonTailRemover(mRequestContext));
306 arrayToRelease.AppendElement(nonTailRemover.forget());
307 }
308
309 NS_DispatchToMainThread(new ProxyReleaseRunnable(std::move(arrayToRelease)));
310}
311
312void HttpBaseChannel::AddClassificationFlags(uint32_t aClassificationFlags,
313 bool aIsThirdParty) {
314 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
316 "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)
317 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)
;
318
319 if (aIsThirdParty) {
320 mThirdPartyClassificationFlags |= aClassificationFlags;
321 } else {
322 mFirstPartyClassificationFlags |= aClassificationFlags;
323 }
324}
325
326static bool isSecureOrTrustworthyURL(nsIURI* aURI) {
327 return aURI->SchemeIs("https") ||
328 (StaticPrefs::network_http_encoding_trustworthy_is_https() &&
329 nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI));
330}
331
332nsresult HttpBaseChannel::Init(nsIURI* aURI, uint32_t aCaps,
333 nsProxyInfo* aProxyInfo,
334 uint32_t aProxyResolveFlags, nsIURI* aProxyURI,
335 uint64_t aChannelId, nsILoadInfo* aLoadInfo) {
336 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)
;
337
338 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"
, 338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "null uri"
")"); do { MOZ_CrashSequence(__null, 338); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
339
340 mURI = aURI;
341 mOriginalURI = aURI;
342 mDocumentURI = nullptr;
343 mCaps = aCaps;
344 mProxyResolveFlags = aProxyResolveFlags;
345 mProxyURI = aProxyURI;
346 mChannelId = aChannelId;
347 mLoadInfo = aLoadInfo;
348
349 // Construct connection info object
350 nsAutoCString host;
351 int32_t port = -1;
352 bool isHTTPS = isSecureOrTrustworthyURL(mURI);
353
354 nsresult rv = mURI->GetAsciiHost(host);
355 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
356
357 // Reject the URL if it doesn't specify a host
358 if (host.IsEmpty()) return NS_ERROR_MALFORMED_URI;
359
360 rv = mURI->GetPort(&port);
361 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
362
363 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)
;
364
365 rv = mURI->GetAsciiSpec(mSpec);
366 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
367 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)
;
368
369 // Assert default request method
370 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", 370
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestHead.EqualsMethod(nsHttpRequestHead::kMethod_Get)"
")"); do { MOZ_CrashSequence(__null, 370); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
371
372 // Set request headers
373 nsAutoCString hostLine;
374 rv = nsHttpHandler::GenerateHostPort(host, port, hostLine);
375 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
376
377 rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
378 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
379
380 // Override the Accept header if a specific MediaDocument kind is forced.
381 ExtContentPolicy contentPolicyType =
382 mLoadInfo->GetExternalContentPolicyType();
383 // TRRLoadInfo doesn't implement GetForceMediaDocument.
384 ForceMediaDocument forceMediaDocument;
385 if (NS_SUCCEEDED(mLoadInfo->GetForceMediaDocument(&forceMediaDocument))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetForceMediaDocument
(&forceMediaDocument))), 1)))
) {
386 switch (forceMediaDocument) {
387 case ForceMediaDocument::Image:
388 contentPolicyType = ExtContentPolicy::TYPE_IMAGE;
389 break;
390 case ForceMediaDocument::Video:
391 contentPolicyType = ExtContentPolicy::TYPE_MEDIA;
392 break;
393 case ForceMediaDocument::None:
394 break;
395 }
396 }
397
398 RefPtr<mozilla::dom::BrowsingContext> browsingContext;
399 mLoadInfo->GetBrowsingContext(getter_AddRefs(browsingContext));
400 if (!browsingContext) {
401 mLoadInfo->GetAssociatedBrowsingContext(getter_AddRefs(browsingContext));
402 }
403
404 const nsCString& languageOverride =
405 browsingContext ? browsingContext->Top()->GetLanguageOverride()
406 : EmptyCString();
407
408 rv = gHttpHandler->AddStandardRequestHeaders(
409 &mRequestHead, aURI, isHTTPS, contentPolicyType,
410 nsContentUtils::ShouldResistFingerprinting(this,
411 RFPTarget::HttpUserAgent),
412 languageOverride);
413 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
414
415 nsAutoCString type;
416 if (aProxyInfo && NS_SUCCEEDED(aProxyInfo->GetType(type))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProxyInfo->GetType
(type))), 1)))
&&
417 !type.EqualsLiteral("unknown")) {
418 mProxyInfo = aProxyInfo;
419 }
420
421 mCurrentThread = GetCurrentSerialEventTarget();
422 return rv;
423}
424
425//-----------------------------------------------------------------------------
426// HttpBaseChannel::nsISupports
427//-----------------------------------------------------------------------------
428
429NS_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"
, 429); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); 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"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("HttpBaseChannel"), (uint32_t
)(sizeof(*this))); return count; }
430NS_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"
, 430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 430
); __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", 430
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 430); __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; }
431
432NS_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"
, 432); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
433 NS_INTERFACE_MAP_ENTRY(nsIRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequest>)) foundInterface = static_cast
<nsIRequest*>(this); else
434 NS_INTERFACE_MAP_ENTRY(nsIChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIChannel>)) foundInterface = static_cast
<nsIChannel*>(this); else
435 NS_INTERFACE_MAP_ENTRY(nsIIdentChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIIdentChannel>)) foundInterface
= static_cast<nsIIdentChannel*>(this); else
436 NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIEncodedChannel>)) foundInterface
= static_cast<nsIEncodedChannel*>(this); else
437 NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannel>)) foundInterface =
static_cast<nsIHttpChannel*>(this); else
438 NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannelInternal>)) foundInterface
= static_cast<nsIHttpChannelInternal*>(this); else
439 NS_INTERFACE_MAP_ENTRY(nsIForcePendingChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIForcePendingChannel>)) foundInterface
= static_cast<nsIForcePendingChannel*>(this); else
440 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel>)) foundInterface
= static_cast<nsIUploadChannel*>(this); else
441 NS_INTERFACE_MAP_ENTRY(nsIFormPOSTActionChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIFormPOSTActionChannel>)) foundInterface
= static_cast<nsIFormPOSTActionChannel*>(this); else
442 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel2>)) foundInterface
= static_cast<nsIUploadChannel2*>(this); else
443 NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsPriority>)) foundInterface
= static_cast<nsISupportsPriority*>(this); else
444 NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsITraceableChannel>)) foundInterface
= static_cast<nsITraceableChannel*>(this); else
445 NS_INTERFACE_MAP_ENTRY(nsIPrivateBrowsingChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIPrivateBrowsingChannel>)) foundInterface
= static_cast<nsIPrivateBrowsingChannel*>(this); else
446 NS_INTERFACE_MAP_ENTRY(nsITimedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsITimedChannel>)) foundInterface
= static_cast<nsITimedChannel*>(this); else
447 NS_INTERFACE_MAP_ENTRY(nsIConsoleReportCollector)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIConsoleReportCollector>)) foundInterface
= static_cast<nsIConsoleReportCollector*>(this); else
448 NS_INTERFACE_MAP_ENTRY(nsIThrottledInputChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThrottledInputChannel>)) foundInterface
= static_cast<nsIThrottledInputChannel*>(this); else
449 NS_INTERFACE_MAP_ENTRY(nsIClassifiedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIClassifiedChannel>)) foundInterface
= static_cast<nsIClassifiedChannel*>(this); else
450 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
451NS_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; }
452
453//-----------------------------------------------------------------------------
454// HttpBaseChannel::nsIRequest
455//-----------------------------------------------------------------------------
456
457NS_IMETHODIMPnsresult
458HttpBaseChannel::GetName(nsACString& aName) {
459 aName = mSpec;
460 return NS_OK;
461}
462
463NS_IMETHODIMPnsresult
464HttpBaseChannel::IsPending(bool* aIsPending) {
465 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"
, 465); return NS_ERROR_INVALID_POINTER; } } while (false)
;
466 *aIsPending = LoadIsPending() || LoadForcePending();
467 return NS_OK;
468}
469
470NS_IMETHODIMPnsresult
471HttpBaseChannel::GetStatus(nsresult* aStatus) {
472 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", 472
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
473 *aStatus = mStatus;
474 return NS_OK;
475}
476
477NS_IMETHODIMPnsresult
478HttpBaseChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
479 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"
, 479); return NS_ERROR_INVALID_POINTER; } } while (false)
;
480 *aLoadGroup = do_AddRef(mLoadGroup).take();
481 return NS_OK;
482}
483
484NS_IMETHODIMPnsresult
485HttpBaseChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
486 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"
, 486); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should only be called on the main thread." ")"); do {
MOZ_CrashSequence(__null, 486); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
487
488 if (!CanSetLoadGroup(aLoadGroup)) {
489 return NS_ERROR_FAILURE;
490 }
491
492 mLoadGroup = aLoadGroup;
493 mProgressSink = nullptr;
494 UpdatePrivateBrowsing();
495 return NS_OK;
496}
497
498NS_IMETHODIMPnsresult
499HttpBaseChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
500 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"
, 500); return NS_ERROR_INVALID_POINTER; } } while (false)
;
501 *aLoadFlags = mLoadFlags;
502 return NS_OK;
503}
504
505NS_IMETHODIMPnsresult
506HttpBaseChannel::SetLoadFlags(nsLoadFlags aLoadFlags) {
507 mLoadFlags = aLoadFlags;
508 return NS_OK;
509}
510
511NS_IMETHODIMPnsresult
512HttpBaseChannel::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
513 if (!LoadIsOCSP()) {
514 return GetTRRModeImpl(aTRRMode);
515 }
516
517 nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID"@mozilla.org/network/dns-service;1");
518 nsIDNSService::ResolverMode trrMode = nsIDNSService::MODE_NATIVEONLY;
519 // If this is an OCSP channel, and the global TRR mode is TRR_ONLY (3)
520 // then we set the mode for this channel as TRR_DISABLED_MODE.
521 // We do this to prevent a TRR service channel's OCSP validation from
522 // blocking DNS resolution completely.
523 if (dns && NS_SUCCEEDED(dns->GetCurrentTrrMode(&trrMode))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dns->GetCurrentTrrMode
(&trrMode))), 1)))
&&
524 trrMode == nsIDNSService::MODE_TRRONLY) {
525 *aTRRMode = nsIRequest::TRR_DISABLED_MODE;
526 return NS_OK;
527 }
528
529 return GetTRRModeImpl(aTRRMode);
530}
531
532NS_IMETHODIMPnsresult
533HttpBaseChannel::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
534 return SetTRRModeImpl(aTRRMode);
535}
536
537NS_IMETHODIMPnsresult
538HttpBaseChannel::SetDocshellUserAgentOverride() {
539 RefPtr<dom::BrowsingContext> bc;
540 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", 540
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))"
")"); do { MOZ_CrashSequence(__null, 540); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
541 if (!bc) {
542 return NS_OK;
543 }
544
545 nsAutoCString customUserAgent;
546 bc->GetCustomUserAgent(customUserAgent);
547 if (customUserAgent.IsEmpty() || customUserAgent.IsVoid()) {
548 return NS_OK;
549 }
550
551 nsresult rv = SetRequestHeaderInternal(
552 "User-Agent"_ns, customUserAgent, false,
553 nsHttpHeaderArray::eVarietyRequestEnforceDefault);
554 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
555 return rv;
556 }
557
558 return NS_OK;
559}
560
561//-----------------------------------------------------------------------------
562// HttpBaseChannel::nsIChannel
563//-----------------------------------------------------------------------------
564
565NS_IMETHODIMPnsresult
566HttpBaseChannel::GetOriginalURI(nsIURI** aOriginalURI) {
567 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"
, 567); return NS_ERROR_INVALID_POINTER; } } while (false)
;
568 *aOriginalURI = do_AddRef(mOriginalURI).take();
569 return NS_OK;
570}
571
572NS_IMETHODIMPnsresult
573HttpBaseChannel::SetOriginalURI(nsIURI* aOriginalURI) {
574 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 574); 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"
, 574, 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"
, 574); } } 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", 574
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
575
576 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"
, 576); return NS_ERROR_INVALID_POINTER; } } while (false)
;
577 mOriginalURI = aOriginalURI;
578 return NS_OK;
579}
580
581NS_IMETHODIMPnsresult
582HttpBaseChannel::GetURI(nsIURI** aURI) {
583 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", 583
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
584 *aURI = do_AddRef(mURI).take();
585 return NS_OK;
586}
587
588NS_IMETHODIMPnsresult
589HttpBaseChannel::GetOwner(nsISupports** aOwner) {
590 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", 590
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
591 *aOwner = do_AddRef(mOwner).take();
592 return NS_OK;
593}
594
595NS_IMETHODIMPnsresult
596HttpBaseChannel::SetOwner(nsISupports* aOwner) {
597 mOwner = aOwner;
598 return NS_OK;
599}
600
601NS_IMETHODIMPnsresult
602HttpBaseChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) {
603 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"
, 603); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aLoadInfo"
") (" "loadinfo can't be null" ")"); do { MOZ_CrashSequence(
__null, 603); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
604 mLoadInfo = aLoadInfo;
605 return NS_OK;
606}
607
608NS_IMETHODIMPnsresult
609HttpBaseChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) {
610 *aLoadInfo = do_AddRef(mLoadInfo).take();
611 return NS_OK;
612}
613
614NS_IMETHODIMPnsresult
615HttpBaseChannel::GetIsDocument(bool* aIsDocument) {
616 return NS_GetIsDocumentChannel(this, aIsDocument);
617}
618
619NS_IMETHODIMPnsresult
620HttpBaseChannel::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks) {
621 *aCallbacks = do_AddRef(mCallbacks).take();
622 return NS_OK;
623}
624
625NS_IMETHODIMPnsresult
626HttpBaseChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
627 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"
, 627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should only be called on the main thread." ")"); do {
MOZ_CrashSequence(__null, 627); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
628
629 if (!CanSetCallbacks(aCallbacks)) {
630 return NS_ERROR_FAILURE;
631 }
632
633 mCallbacks = aCallbacks;
634 mProgressSink = nullptr;
635
636 UpdatePrivateBrowsing();
637 return NS_OK;
638}
639
640NS_IMETHODIMPnsresult
641HttpBaseChannel::GetContentType(nsACString& aContentType) {
642 if (!mResponseHead) {
643 aContentType.Truncate();
644 return NS_ERROR_NOT_AVAILABLE;
645 }
646
647 mResponseHead->ContentType(aContentType);
648 if (!aContentType.IsEmpty()) {
649 return NS_OK;
650 }
651
652 aContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type");
653 return NS_OK;
654}
655
656NS_IMETHODIMPnsresult
657HttpBaseChannel::SetContentType(const nsACString& aContentType) {
658 if (mListener || LoadWasOpened() || mDummyChannelForCachedResource) {
659 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
660
661 nsAutoCString contentTypeBuf, charsetBuf;
662 bool hadCharset;
663 net_ParseContentType(aContentType, contentTypeBuf, charsetBuf, &hadCharset);
664
665 mResponseHead->SetContentType(contentTypeBuf);
666
667 // take care not to stomp on an existing charset
668 if (hadCharset) mResponseHead->SetContentCharset(charsetBuf);
669
670 } else {
671 // We are being given a content-type hint.
672 bool dummy;
673 net_ParseContentType(aContentType, mContentTypeHint, mContentCharsetHint,
674 &dummy);
675 }
676
677 return NS_OK;
678}
679
680NS_IMETHODIMPnsresult
681HttpBaseChannel::GetContentCharset(nsACString& aContentCharset) {
682 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
683
684 mResponseHead->ContentCharset(aContentCharset);
685 return NS_OK;
686}
687
688NS_IMETHODIMPnsresult
689HttpBaseChannel::SetContentCharset(const nsACString& aContentCharset) {
690 if (mListener) {
691 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
692
693 mResponseHead->SetContentCharset(aContentCharset);
694 } else {
695 // Charset hint
696 mContentCharsetHint = aContentCharset;
697 }
698 return NS_OK;
699}
700
701NS_IMETHODIMPnsresult
702HttpBaseChannel::GetContentDisposition(uint32_t* aContentDisposition) {
703 if (mLoadInfo->GetForceMediaDocument() != ForceMediaDocument::None) {
704 *aContentDisposition = nsIChannel::DISPOSITION_FORCE_INLINE;
705 return NS_OK;
706 }
707
708 // See bug 1658877. If mContentDispositionHint is already
709 // DISPOSITION_ATTACHMENT, it means this channel is created from a
710 // download attribute. In this case, we should prefer the value from the
711 // download attribute rather than the value in content disposition header.
712 // DISPOSITION_FORCE_INLINE is used to explicitly set inline, used by
713 // the pdf reader when loading a attachment pdf without having to
714 // download it.
715 if (mContentDispositionHint == nsIChannel::DISPOSITION_ATTACHMENT ||
716 mContentDispositionHint == nsIChannel::DISPOSITION_FORCE_INLINE) {
717 *aContentDisposition = mContentDispositionHint;
718 return NS_OK;
719 }
720
721 nsresult rv;
722 nsCString header;
723
724 rv = GetContentDispositionHeader(header);
725 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
726 if (mContentDispositionHint == UINT32_MAX(4294967295U)) return rv;
727
728 *aContentDisposition = mContentDispositionHint;
729 return NS_OK;
730 }
731
732 *aContentDisposition = NS_GetContentDispositionFromHeader(header, this);
733 return NS_OK;
734}
735
736NS_IMETHODIMPnsresult
737HttpBaseChannel::SetContentDisposition(uint32_t aContentDisposition) {
738 mContentDispositionHint = aContentDisposition;
739 return NS_OK;
740}
741
742NS_IMETHODIMPnsresult
743HttpBaseChannel::GetContentDispositionFilename(
744 nsAString& aContentDispositionFilename) {
745 aContentDispositionFilename.Truncate();
746 nsresult rv;
747 nsCString header;
748
749 rv = GetContentDispositionHeader(header);
750 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
751 rv = NS_GetFilenameFromDisposition(aContentDispositionFilename, header);
752 }
753
754 // If we failed to get the filename from header, we should use
755 // mContentDispositionFilename, since mContentDispositionFilename is set from
756 // the download attribute.
757 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
758 if (!mContentDispositionFilename) {
759 return rv;
760 }
761
762 aContentDispositionFilename = *mContentDispositionFilename;
763 return NS_OK;
764 }
765
766 return rv;
767}
768
769NS_IMETHODIMPnsresult
770HttpBaseChannel::SetContentDispositionFilename(
771 const nsAString& aContentDispositionFilename) {
772 mContentDispositionFilename =
773 MakeUnique<nsString>(aContentDispositionFilename);
774
775 // For safety reasons ensure the filename doesn't contain null characters and
776 // replace them with underscores. We may later pass the extension to system
777 // MIME APIs that expect null terminated strings.
778 mContentDispositionFilename->ReplaceChar(char16_t(0), '_');
779
780 return NS_OK;
781}
782
783NS_IMETHODIMPnsresult
784HttpBaseChannel::GetContentDispositionHeader(
785 nsACString& aContentDispositionHeader) {
786 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
787
788 nsresult rv = mResponseHead->GetHeader(nsHttp::Content_Disposition,
789 aContentDispositionHeader);
790 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || aContentDispositionHeader.IsEmpty()) {
791 return NS_ERROR_NOT_AVAILABLE;
792 }
793
794 return NS_OK;
795}
796
797NS_IMETHODIMPnsresult
798HttpBaseChannel::GetContentLength(int64_t* aContentLength) {
799 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"
, 799); return NS_ERROR_INVALID_POINTER; } } while (false)
;
800
801 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
802
803 if (LoadDeliveringAltData()) {
804 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", 804
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAvailableCachedAltDataType.IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 804); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
805 *aContentLength = mAltDataLength;
806 return NS_OK;
807 }
808
809 *aContentLength = mResponseHead->ContentLength();
810 return NS_OK;
811}
812
813NS_IMETHODIMPnsresult
814HttpBaseChannel::SetContentLength(int64_t value) {
815 if (!mDummyChannelForCachedResource) {
816 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"
, 816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "HttpBaseChannel::SetContentLength"
")"); do { MOZ_CrashSequence(__null, 816); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
817 return NS_ERROR_NOT_IMPLEMENTED;
818 }
819 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", 819
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead" ")"
); do { MOZ_CrashSequence(__null, 819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
820 mResponseHead->SetContentLength(value);
821 return NS_OK;
822}
823
824NS_IMETHODIMPnsresult
825HttpBaseChannel::Open(nsIInputStream** aStream) {
826 if (!gHttpHandler->Active()) {
827 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)
;
828 return NS_ERROR_NOT_AVAILABLE;
829 }
830
831 nsCOMPtr<nsIStreamListener> listener;
832 nsresult rv =
833 nsContentSecurityManager::doContentSecurityCheck(this, listener);
834 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"
, 834); return rv; } } while (false)
;
835
836 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"
, 836); return NS_ERROR_IN_PROGRESS; } } while (false)
;
837
838 if (!gHttpHandler->Active()) {
839 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)
;
840 return NS_ERROR_NOT_AVAILABLE;
841 }
842
843 return NS_ImplementChannelOpen(this, aStream);
844}
845
846NS_IMETHODIMPnsresult
847HttpBaseChannel::GetParentProcessChannelHandle(
848 mozilla::dom::ParentProcessChannelHandle** aValue) {
849 *aValue = do_AddRef(mParentProcessChannelHandle).take();
850 return NS_OK;
851}
852
853NS_IMETHODIMPnsresult
854HttpBaseChannel::SetParentProcessChannelHandle(
855 mozilla::dom::ParentProcessChannelHandle* aValue) {
856 if (XRE_IsParentProcess()) {
857 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"
, 858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "SetParentProcessChannelHandle in the parent process would leak"
")"); do { MOZ_CrashSequence(__null, 858); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
858 "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"
, 858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "SetParentProcessChannelHandle in the parent process would leak"
")"); do { MOZ_CrashSequence(__null, 858); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
859 return NS_ERROR_NOT_AVAILABLE;
860 }
861
862 mParentProcessChannelHandle = aValue;
863 return NS_OK;
864}
865
866//-----------------------------------------------------------------------------
867// HttpBaseChannel::nsIUploadChannel
868//-----------------------------------------------------------------------------
869
870NS_IMETHODIMPnsresult
871HttpBaseChannel::GetUploadStream(nsIInputStream** stream) {
872 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", 872
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
873 *stream = do_AddRef(mUploadStream).take();
874 return NS_OK;
875}
876
877NS_IMETHODIMPnsresult
878HttpBaseChannel::SetUploadStream(nsIInputStream* stream,
879 const nsACString& contentTypeArg,
880 int64_t contentLength) {
881 // NOTE: for backwards compatibility and for compatibility with old style
882 // plugins, |stream| may include headers, specifically Content-Type and
883 // Content-Length headers. in this case, |contentType| and |contentLength|
884 // would be unspecified. this is traditionally the case of a POST request,
885 // and so we select POST as the request method if contentType and
886 // contentLength are unspecified.
887
888 if (stream) {
889 nsAutoCString method;
890
891 // This method and ExplicitSetUploadStream mean different things by "empty
892 // content type string". This method means "no header", but
893 // ExplicitSetUploadStream means "header with empty value". So we have to
894 // massage the contentType argument into the form ExplicitSetUploadStream
895 // expects.
896 nsCOMPtr<nsIMIMEInputStream> mimeStream;
897 nsCString contentType(contentTypeArg);
898 if (contentType.IsEmpty()) {
899 contentType.SetIsVoid(true);
900 method = "POST"_ns;
901
902 // MIME streams are a special case, and include headers which need to be
903 // copied to the channel.
904 mimeStream = do_QueryInterface(stream);
905 if (mimeStream) {
906 // Copy non-origin related headers to the channel.
907 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
908 new AddHeadersToChannelVisitor(this);
909 mimeStream->VisitHeaders(visitor);
910
911 return ExplicitSetUploadStream(stream, contentType, contentLength,
912 method);
913 }
914 } else {
915 method = "PUT"_ns;
916
917 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"
, 919); 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, 919); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
918 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"
, 919); 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, 919); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
919 "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"
, 919); 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, 919); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
920 }
921 return ExplicitSetUploadStream(stream, contentType, contentLength, method);
922 }
923
924 // if stream is null, ExplicitSetUploadStream returns error.
925 // So we need special case for GET method.
926 SetRequestMethod("GET"_ns); // revert to GET request
927 mUploadStream = nullptr;
928 return NS_OK;
929}
930
931namespace {
932
933class MIMEHeaderCopyVisitor final : public nsIHttpHeaderVisitor {
934 public:
935 explicit MIMEHeaderCopyVisitor(nsIMIMEInputStream* aDest) : mDest(aDest) {}
936
937 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:
938 NS_IMETHODvirtual nsresult VisitHeader(const nsACString& aName,
939 const nsACString& aValue) override {
940 return mDest->AddHeader(PromiseFlatCStringTPromiseFlatString<char>(aName).get(),
941 PromiseFlatCStringTPromiseFlatString<char>(aValue).get());
942 }
943
944 private:
945 ~MIMEHeaderCopyVisitor() = default;
946
947 nsCOMPtr<nsIMIMEInputStream> mDest;
948};
949
950NS_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"
, 950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 950
); __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"
, 950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MIMEHeaderCopyVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 950); __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"
, 950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 950
); __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"
, 950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MIMEHeaderCopyVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 950); __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"
, 950); 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; }
951
952static void NormalizeCopyComplete(void* aClosure, nsresult aStatus) {
953#ifdef DEBUG1
954 // Called on the STS thread by NS_AsyncCopy
955 nsCOMPtr<nsIEventTarget> sts =
956 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID"@mozilla.org/network/stream-transport-service;1");
957 bool result = false;
958 sts->IsOnCurrentThread(&result);
959 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"
, 959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "result" ") ("
"Should only be called on the STS thread." ")"); do { MOZ_CrashSequence
(__null, 959); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
960#endif
961
962 RefPtr<GenericPromise::Private> ready =
963 already_AddRefed(static_cast<GenericPromise::Private*>(aClosure));
964 if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
965 ready->Resolve(true, __func__);
966 } else {
967 ready->Reject(aStatus, __func__);
968 }
969}
970
971// Normalize the upload stream for a HTTP channel, so that is one of the
972// expected and compatible types. Components like WebExtensions and DevTools
973// expect that upload streams in the parent process are cloneable, seekable, and
974// synchronous to read, which this function helps guarantee somewhat efficiently
975// and without loss of information.
976//
977// If the replacement stream outparameter is not initialized to `nullptr`, the
978// returned stream should be used instead of `aUploadStream` as the upload
979// stream for the HTTP channel, and the previous stream should not be touched
980// again.
981//
982// If aReadyPromise is non-nullptr after the function is called, it is a promise
983// which should be awaited before continuing to `AsyncOpen` the HTTP channel,
984// as the replacement stream will not be ready until it is resolved.
985static nsresult NormalizeUploadStream(nsIInputStream* aUploadStream,
986 nsIInputStream** aReplacementStream,
987 GenericPromise** aReadyPromise) {
988 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", 988
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 988); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
989
990 *aReplacementStream = nullptr;
991 *aReadyPromise = nullptr;
992
993 // Unwrap RemoteLazyInputStream and normalize the contents as we're in the
994 // parent process.
995 if (nsCOMPtr<mozIRemoteLazyInputStream> lazyStream =
996 do_QueryInterface(aUploadStream)) {
997 nsCOMPtr<nsIInputStream> internal;
998 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(lazyStream->TakeInternalStream
(getter_AddRefs(internal)))), 1)))
999 lazyStream->TakeInternalStream(getter_AddRefs(internal)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(lazyStream->TakeInternalStream
(getter_AddRefs(internal)))), 1)))
) {
1000 nsCOMPtr<nsIInputStream> replacement;
1001 nsresult rv = NormalizeUploadStream(internal, getter_AddRefs(replacement),
1002 aReadyPromise);
1003 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"
, 1003); return rv; } } while (false)
;
1004
1005 if (replacement) {
1006 replacement.forget(aReplacementStream);
1007 } else {
1008 internal.forget(aReplacementStream);
1009 }
1010 return NS_OK;
1011 }
1012 }
1013
1014 // Preserve MIME information on the stream when normalizing.
1015 if (nsCOMPtr<nsIMIMEInputStream> mime = do_QueryInterface(aUploadStream)) {
1016 nsCOMPtr<nsIInputStream> data;
1017 nsresult rv = mime->GetData(getter_AddRefs(data));
1018 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"
, 1018); return rv; } } while (false)
;
1019
1020 nsCOMPtr<nsIInputStream> replacement;
1021 rv =
1022 NormalizeUploadStream(data, getter_AddRefs(replacement), aReadyPromise);
1023 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"
, 1023); return rv; } } while (false)
;
1024
1025 if (replacement) {
1026 nsCOMPtr<nsIMIMEInputStream> replacementMime(
1027 do_CreateInstance("@mozilla.org/network/mime-input-stream;1", &rv));
1028 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"
, 1028); return rv; } } while (false)
;
1029
1030 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
1031 new MIMEHeaderCopyVisitor(replacementMime);
1032 rv = mime->VisitHeaders(visitor);
1033 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"
, 1033); return rv; } } while (false)
;
1034
1035 rv = replacementMime->SetData(replacement);
1036 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"
, 1036); return rv; } } while (false)
;
1037
1038 replacementMime.forget(aReplacementStream);
1039 }
1040 return NS_OK;
1041 }
1042
1043 // Preserve "real" buffered input streams which wrap data (i.e. are backed by
1044 // nsBufferedInputStream), but normalize the wrapped stream.
1045 if (nsCOMPtr<nsIBufferedInputStream> buffered =
1046 do_QueryInterface(aUploadStream)) {
1047 nsCOMPtr<nsIInputStream> data;
1048 if (NS_SUCCEEDED(buffered->GetData(getter_AddRefs(data)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(buffered->GetData
(getter_AddRefs(data)))), 1)))
) {
1049 nsCOMPtr<nsIInputStream> replacement;
1050 nsresult rv = NormalizeUploadStream(data, getter_AddRefs(replacement),
1051 aReadyPromise);
1052 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"
, 1052); return rv; } } while (false)
;
1053 if (replacement) {
1054 // This buffer size should be kept in sync with HTMLFormSubmission.
1055 rv = NS_NewBufferedInputStream(aReplacementStream, replacement.forget(),
1056 8192);
1057 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"
, 1057); return rv; } } while (false)
;
1058 }
1059 return NS_OK;
1060 }
1061 }
1062
1063 // Preserve multiplex input streams, normalizing each individual inner stream
1064 // to avoid unnecessary copying.
1065 if (nsCOMPtr<nsIMultiplexInputStream> multiplex =
1066 do_QueryInterface(aUploadStream)) {
1067 uint32_t count = multiplex->GetCount();
1068 nsTArray<nsCOMPtr<nsIInputStream>> streams(count);
1069 nsTArray<RefPtr<GenericPromise>> promises(count);
1070 bool replace = false;
1071 for (uint32_t i = 0; i < count; ++i) {
1072 nsCOMPtr<nsIInputStream> inner;
1073 nsresult rv = multiplex->GetStream(i, getter_AddRefs(inner));
1074 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1074); return rv; } } while (false)
;
1075
1076 RefPtr<GenericPromise> promise;
1077 nsCOMPtr<nsIInputStream> replacement;
1078 rv = NormalizeUploadStream(inner, getter_AddRefs(replacement),
1079 getter_AddRefs(promise));
1080 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"
, 1080); return rv; } } while (false)
;
1081 if (promise) {
1082 promises.AppendElement(promise);
1083 }
1084 if (replacement) {
1085 streams.AppendElement(replacement);
1086 replace = true;
1087 } else {
1088 streams.AppendElement(inner);
1089 }
1090 }
1091
1092 // If any of the inner streams needed to be replaced, replace the entire
1093 // nsIMultiplexInputStream.
1094 if (replace) {
1095 nsresult rv;
1096 nsCOMPtr<nsIMultiplexInputStream> replacement =
1097 do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1", &rv);
1098 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"
, 1098); return rv; } } while (false)
;
1099 for (auto& stream : streams) {
1100 rv = replacement->AppendStream(stream);
1101 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"
, 1101); return rv; } } while (false)
;
1102 }
1103
1104 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", 1104
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(CallQueryInterface(replacement, aReplacementStream))"
")"); do { MOZ_CrashSequence(__null, 1104); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1105 }
1106
1107 // Wait for all inner promises to settle before resolving the final promise.
1108 if (!promises.IsEmpty()) {
1109 RefPtr<GenericPromise> ready =
1110 GenericPromise::AllSettled(GetCurrentSerialEventTarget(), promises)
1111 ->Then(GetCurrentSerialEventTarget(), __func__,
1112 [](GenericPromise::AllSettledPromiseType::
1113 ResolveOrRejectValue&& aResults)
1114 -> RefPtr<GenericPromise> {
1115 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"
, 1116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aResults.IsResolve()"
") (" "AllSettled never rejects" ")"); do { MOZ_CrashSequence
(__null, 1116); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1116 "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"
, 1116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aResults.IsResolve()"
") (" "AllSettled never rejects" ")"); do { MOZ_CrashSequence
(__null, 1116); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1117 for (auto& result : aResults.ResolveValue()) {
1118 if (result.IsReject()) {
1119 return GenericPromise::CreateAndReject(
1120 result.RejectValue(), __func__);
1121 }
1122 }
1123 return GenericPromise::CreateAndResolve(true, __func__);
1124 });
1125 ready.forget(aReadyPromise);
1126 }
1127 return NS_OK;
1128 }
1129
1130 // If the stream is cloneable, seekable and non-async, we can allow it. Async
1131 // input streams can cause issues, as various consumers of input streams
1132 // expect the payload to be synchronous and `Available()` to be the length of
1133 // the stream, which is not true for asynchronous streams.
1134 nsCOMPtr<nsIAsyncInputStream> async = do_QueryInterface(aUploadStream);
1135 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(aUploadStream);
1136 if (NS_InputStreamIsCloneable(aUploadStream) && seekable && !async) {
1137 return NS_OK;
1138 }
1139
1140 // Asynchronously copy our non-normalized stream into a StorageStream so that
1141 // it is seekable, cloneable, and synchronous once the copy completes.
1142
1143 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"
, 1143)
;
1144
1145 // nsStorageStream requires a power-of-two segment size.
1146 static constexpr uint32_t kMinCopySegmentSize = 4 * 1024;
1147 static constexpr uint32_t kMaxCopySegmentSize = 1u << 31;
1148 const uint32_t maxCopySegmentSize = RoundUpPow2(
1149 std::clamp(StaticPrefs::network_http_upload_copy_max_segment_size(),
1150 kMinCopySegmentSize, kMaxCopySegmentSize));
1151 uint32_t segmentSize = maxCopySegmentSize;
1152 int64_t length;
1153 if (InputStreamLengthHelper::GetSyncLength(aUploadStream, &length) &&
1154 length >= 0) {
1155 segmentSize = RoundUpPow2(
1156 std::clamp<int64_t>(length, kMinCopySegmentSize, maxCopySegmentSize));
1157 }
1158
1159 nsCOMPtr<nsIStorageStream> storageStream;
1160 nsresult rv = NS_NewStorageStream(segmentSize, UINT32_MAX(4294967295U),
1161 getter_AddRefs(storageStream));
1162 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"
, 1162); return rv; } } while (false)
;
1163
1164 nsCOMPtr<nsIOutputStream> sink;
1165 rv = storageStream->GetOutputStream(0, getter_AddRefs(sink));
1166 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"
, 1166); return rv; } } while (false)
;
1167
1168 nsCOMPtr<nsIInputStream> replacementStream;
1169 rv = storageStream->NewInputStream(0, getter_AddRefs(replacementStream));
1170 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"
, 1170); return rv; } } while (false)
;
1171
1172 // Ensure the source stream is buffered before starting the copy so we can use
1173 // ReadSegments, as nsStorageStream doesn't implement WriteSegments.
1174 nsCOMPtr<nsIInputStream> source = aUploadStream;
1175 if (!NS_InputStreamIsBuffered(aUploadStream)) {
1176 nsCOMPtr<nsIInputStream> bufferedSource;
1177 rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedSource),
1178 source.forget(), segmentSize);
1179 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"
, 1179); return rv; } } while (false)
;
1180 source = bufferedSource.forget();
1181 }
1182
1183 // Perform an AsyncCopy into the input stream on the STS.
1184 nsCOMPtr<nsIEventTarget> target =
1185 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID"@mozilla.org/network/stream-transport-service;1");
1186 RefPtr<GenericPromise::Private> ready = new GenericPromise::Private(__func__);
1187 rv =
1188 NS_AsyncCopy(source, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
1189 segmentSize, NormalizeCopyComplete, do_AddRef(ready).take());
1190 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"
, 1190)
) {
1191 ready.get()->Release();
1192 return rv;
1193 }
1194
1195 replacementStream.forget(aReplacementStream);
1196 ready.forget(aReadyPromise);
1197 return NS_OK;
1198}
1199
1200} // anonymous namespace
1201
1202NS_IMETHODIMPnsresult
1203HttpBaseChannel::CloneUploadStream(int64_t* aContentLength,
1204 nsIInputStream** aClonedStream) {
1205 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"
, 1205); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1206 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"
, 1206); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1207 *aClonedStream = nullptr;
1208
1209 if (!XRE_IsParentProcess()) {
1210 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"
, 1210)
;
1211 return NS_ERROR_NOT_AVAILABLE;
1212 }
1213
1214 if (!mUploadStream) {
1215 return NS_OK;
1216 }
1217
1218 // Teeing an async pipe would buffer an upload of unbounded size in memory,
1219 // so report no clone.
1220 if (LoadUploadStreamIsStreaming()) {
1221 *aContentLength = -1;
1222 return NS_OK;
1223 }
1224
1225 nsCOMPtr<nsIInputStream> clonedStream;
1226 nsresult rv =
1227 NS_CloneInputStream(mUploadStream, getter_AddRefs(clonedStream));
1228 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"
, 1228); return rv; } } while (false)
;
1229
1230 clonedStream.forget(aClonedStream);
1231
1232 *aContentLength = mReqContentLength;
1233 return NS_OK;
1234}
1235
1236//-----------------------------------------------------------------------------
1237// HttpBaseChannel::nsIUploadChannel2
1238//-----------------------------------------------------------------------------
1239
1240NS_IMETHODIMPnsresult
1241HttpBaseChannel::ExplicitSetUploadStream(nsIInputStream* aStream,
1242 const nsACString& aContentType,
1243 int64_t aContentLength,
1244 const nsACString& aMethod) {
1245 // Ensure stream is set and method is valid
1246 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", 1246
); return NS_ERROR_FAILURE; } } while (false)
;
1247
1248 nsresult rv = SetRequestMethod(aMethod);
1249 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"
, 1249); return rv; } } while (false)
;
1250
1251 if (!aContentType.IsVoid()) {
1252 if (aContentType.IsEmpty()) {
1253 SetEmptyRequestHeader("Content-Type"_ns);
1254 } else {
1255 SetRequestHeader("Content-Type"_ns, aContentType, false);
1256 }
1257 }
1258
1259 return InternalSetUploadStream(aStream, aContentLength, true);
1260}
1261
1262nsresult HttpBaseChannel::InternalSetUploadStream(
1263 nsIInputStream* aUploadStream, int64_t aContentLength,
1264 bool aSetContentLengthHeader) {
1265 // If we're not on the main thread, such as for TRR, the content length must
1266 // be provided, as we can't normalize our upload stream.
1267 if (!NS_IsMainThread()) {
1268 if (aContentLength < 0) {
1269 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", 1270
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Upload content length must be explicit off-main-thread" ")"
); do { MOZ_CrashSequence(__null, 1270); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1270 "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", 1270
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Upload content length must be explicit off-main-thread" ")"
); do { MOZ_CrashSequence(__null, 1270); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1271 return NS_ERROR_INVALID_ARG;
1272 }
1273
1274 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(aUploadStream);
1275 if (!NS_InputStreamIsCloneable(aUploadStream) || !seekable) {
1276 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"
, 1277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Upload stream must be cloneable & seekable off-main-thread"
")"); do { MOZ_CrashSequence(__null, 1277); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1277 "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"
, 1277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Upload stream must be cloneable & seekable off-main-thread"
")"); do { MOZ_CrashSequence(__null, 1277); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1278 return NS_ERROR_INVALID_ARG;
1279 }
1280
1281 mUploadStream = aUploadStream;
1282 ExplicitSetUploadStreamLength(aContentLength, aSetContentLengthHeader);
1283 return NS_OK;
1284 }
1285
1286 // For streaming uploads (JS ReadableStream body), the stream is an async
1287 // pipe fed by FetchStreamReader. It cannot be normalized (buffered into a
1288 // StorageStream) because it's consumed incrementally. Skip normalization
1289 // entirely and use the pipe as-is.
1290 if (LoadUploadStreamIsStreaming()) {
1291 mUploadStream = aUploadStream;
1292 // mReqContentLength stays 0: the length genuinely is not known yet.
1293 // nsHttpTransaction::Init consults RequestBodyIsStreaming() so that it
1294 // does not mistake that for "no body".
1295 return NS_OK;
1296 }
1297
1298 // Normalize the upload stream we're provided to ensure that it is cloneable,
1299 // seekable, and synchronous when in the parent process.
1300 //
1301 // This might be an async operation, in which case ready will be returned and
1302 // resolved when the operation is complete.
1303 nsCOMPtr<nsIInputStream> replacement;
1304 RefPtr<GenericPromise> ready;
1305 if (XRE_IsParentProcess()) {
1306 nsresult rv = NormalizeUploadStream(
1307 aUploadStream, getter_AddRefs(replacement), getter_AddRefs(ready));
1308 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"
, 1308); return rv; } } while (false)
;
1309 }
1310
1311 mUploadStream = replacement ? replacement.get() : aUploadStream;
1312
1313 // Once the upload stream is ready, fetch its length before proceeding with
1314 // AsyncOpen.
1315 auto onReady = [self = RefPtr{this}, aContentLength, aSetContentLengthHeader,
1316 stream = mUploadStream]() {
1317 auto setLengthAndResume = [self, aSetContentLengthHeader](int64_t aLength) {
1318 self->StorePendingUploadStreamNormalization(false);
1319 self->ExplicitSetUploadStreamLength(aLength >= 0 ? aLength : 0,
1320 aSetContentLengthHeader);
1321 self->MaybeResumeAsyncOpen();
1322 };
1323
1324 if (aContentLength >= 0) {
1325 setLengthAndResume(aContentLength);
1326 return;
1327 }
1328
1329 int64_t length;
1330 if (InputStreamLengthHelper::GetSyncLength(stream, &length)) {
1331 setLengthAndResume(length);
1332 return;
1333 }
1334
1335 InputStreamLengthHelper::GetAsyncLength(stream, setLengthAndResume);
1336 };
1337 StorePendingUploadStreamNormalization(true);
1338
1339 // Resolve onReady synchronously unless a promise is returned.
1340 if (ready) {
1341 ready->Then(GetCurrentSerialEventTarget(), __func__,
1342 [onReady = std::move(onReady)](
1343 GenericPromise::ResolveOrRejectValue&&) { onReady(); });
1344 } else {
1345 onReady();
1346 }
1347 return NS_OK;
1348}
1349
1350void HttpBaseChannel::ExplicitSetUploadStreamLength(
1351 uint64_t aContentLength, bool aSetContentLengthHeader) {
1352 // We already have the content length. We don't need to determinate it.
1353 mReqContentLength = aContentLength;
1354
1355 if (!aSetContentLengthHeader) {
1356 return;
1357 }
1358
1359 nsAutoCString header;
1360 header.AssignLiteral("Content-Length");
1361
1362 // Maybe the content-length header has been already set.
1363 nsAutoCString value;
1364 nsresult rv = GetRequestHeader(header, value);
1365 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !value.IsEmpty()) {
1366 return;
1367 }
1368
1369 nsAutoCString contentLengthStr;
1370 contentLengthStr.AppendInt(aContentLength);
1371 SetRequestHeader(header, contentLengthStr, false);
1372}
1373
1374bool HttpBaseChannel::MaybeWaitForUploadStreamNormalization(
1375 nsIStreamListener* aListener, nsISupports* aContext) {
1376 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", 1376
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 1376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1377 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"
, 1378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadAsyncOpenWaitingForStreamNormalization()"
") (" "AsyncOpen() called twice?" ")"); do { MOZ_CrashSequence
(__null, 1378); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1378 "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"
, 1378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadAsyncOpenWaitingForStreamNormalization()"
") (" "AsyncOpen() called twice?" ")"); do { MOZ_CrashSequence
(__null, 1378); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1379
1380 if (!LoadPendingUploadStreamNormalization()) {
1381 return false;
1382 }
1383
1384 mListener = aListener;
1385 StoreAsyncOpenWaitingForStreamNormalization(true);
1386 return true;
1387}
1388
1389void HttpBaseChannel::MaybeResumeAsyncOpen() {
1390 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", 1390
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 1390); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1391 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", 1391
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadPendingUploadStreamNormalization()"
")"); do { MOZ_CrashSequence(__null, 1391); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1392
1393 if (!LoadAsyncOpenWaitingForStreamNormalization()) {
1394 return;
1395 }
1396
1397 nsCOMPtr<nsIStreamListener> listener;
1398 listener.swap(mListener);
1399
1400 StoreAsyncOpenWaitingForStreamNormalization(false);
1401
1402 nsresult rv = AsyncOpen(listener);
1403 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"
, 1403)
) {
1404 DoAsyncAbort(rv);
1405 }
1406}
1407
1408//-----------------------------------------------------------------------------
1409// HttpBaseChannel::nsIEncodedChannel
1410//-----------------------------------------------------------------------------
1411
1412NS_IMETHODIMPnsresult
1413HttpBaseChannel::GetApplyConversion(bool* value) {
1414 *value = LoadApplyConversion();
1415 return NS_OK;
1416}
1417
1418NS_IMETHODIMPnsresult
1419HttpBaseChannel::SetApplyConversion(bool value) {
1420 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)
1421 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)
;
1422 StoreApplyConversion(value);
1423 return NS_OK;
1424}
1425
1426nsresult HttpBaseChannel::DoApplyContentConversions(
1427 nsIStreamListener* aNextListener, nsIStreamListener** aNewNextListener) {
1428 return DoApplyContentConversionsInternal(aNextListener, aNewNextListener,
1429 false, nullptr);
1430}
1431
1432// create a listener chain that looks like this
1433// http-channel -> decompressor (n times) -> InterceptFailedOnSTop ->
1434// channel-creator-listener
1435//
1436// we need to do this because not every decompressor has fully streamed output
1437// so may need a call to OnStopRequest to identify its completion state.. and if
1438// it creates an error there the channel status code needs to be updated before
1439// calling the terminal listener. Having the decompress do it via cancel() means
1440// channels cannot effectively be used in two contexts (specifically this one
1441// and a peek context for sniffing)
1442//
1443class InterceptFailedOnStop : public nsIThreadRetargetableStreamListener {
1444 virtual ~InterceptFailedOnStop() = default;
1445 nsCOMPtr<nsIStreamListener> mNext;
1446 HttpBaseChannel* mChannel;
1447
1448 public:
1449 InterceptFailedOnStop(nsIStreamListener* arg, HttpBaseChannel* chan)
1450 : mNext(arg), mChannel(chan) {}
1451 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:
1452 NS_DECL_NSITHREADRETARGETABLESTREAMLISTENERvirtual nsresult CheckListenerChain(void) override; virtual nsresult
OnDataFinished(nsresult aStatusCode) override;
1453
1454 NS_IMETHODvirtual nsresult OnStartRequest(nsIRequest* aRequest) override {
1455 nsCOMPtr<nsIStreamListener> next = mNext;
1456 return next->OnStartRequest(aRequest);
1457 }
1458
1459 NS_IMETHODvirtual nsresult OnStopRequest(nsIRequest* aRequest,
1460 nsresult aStatusCode) override {
1461 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)))
) {
1462 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)
1463 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)
;
1464 mChannel->mStatus = aStatusCode;
1465 }
1466 nsCOMPtr<nsIStreamListener> next = mNext;
1467 return next->OnStopRequest(aRequest, aStatusCode);
1468 }
1469
1470 NS_IMETHODvirtual nsresult OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream,
1471 uint64_t aOffset, uint32_t aCount) override {
1472 nsCOMPtr<nsIStreamListener> next = mNext;
1473 return next->OnDataAvailable(aRequest, aInputStream, aOffset, aCount);
1474 }
1475};
1476
1477NS_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"
, 1477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); 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");
nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("InterceptFailedOnStop"
), (uint32_t)(sizeof(*this))); return count; }
1478NS_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"
, 1478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1478
); __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"
, 1478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"InterceptFailedOnStop\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1478); __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; }
1479
1480NS_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"
, 1480); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
1481 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIStreamListener>)) foundInterface
= static_cast<nsIStreamListener*>(this); else
1482 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestObserver>)) foundInterface
= static_cast<nsIRequestObserver*>(this); else
1483 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableStreamListener>
)) foundInterface = static_cast<nsIThreadRetargetableStreamListener
*>(this); else
1484 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
1485NS_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"
, 1485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 1485); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
1486
1487NS_IMETHODIMPnsresult
1488InterceptFailedOnStop::CheckListenerChain() {
1489 nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
1490 do_QueryInterface(mNext);
1491 if (!listener) {
1492 return NS_ERROR_NO_INTERFACE;
1493 }
1494
1495 return listener->CheckListenerChain();
1496}
1497
1498NS_IMETHODIMPnsresult
1499InterceptFailedOnStop::OnDataFinished(nsresult aStatus) {
1500 nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
1501 do_QueryInterface(mNext);
1502 if (listener) {
1503 return listener->OnDataFinished(aStatus);
1504 }
1505
1506 return NS_OK;
1507}
1508
1509NS_IMETHODIMPnsresult
1510HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener,
1511 nsIStreamListener** aNewNextListener,
1512 nsISupports* aCtxt) {
1513 return DoApplyContentConversionsInternal(aNextListener, aNewNextListener,
1514 false, aCtxt);
1515}
1516
1517nsresult HttpBaseChannel::DoApplyContentConversionsInternal(
1518 nsIStreamListener* aNextListener, nsIStreamListener** aNewNextListener,
1519 bool aRemoveEncodings, nsISupports* aCtxt) {
1520 *aNewNextListener = nullptr;
1521 if (!mResponseHead || !aNextListener) {
1522 return NS_OK;
1523 }
1524
1525 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
1527 "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)
1528 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)
;
1529
1530#ifdef DEBUG1
1531 {
1532 nsAutoCString contentEncoding;
1533 nsresult rv =
1534 mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
1535 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !contentEncoding.IsEmpty()) {
1536 nsAutoCString newEncoding;
1537 char* cePtr = contentEncoding.BeginWriting();
1538 while (char* val = nsCRT::strtok(cePtr, HTTP_LWS" \t" ",", &cePtr)) {
1539 if (strcmp(val, "dcb") == 0 || strcmp(val, "dcz") == 0) {
1540 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", 1540
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadApplyConversion() && !LoadHasAppliedConversion()"
")"); do { MOZ_CrashSequence(__null, 1540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1541 }
1542 }
1543 }
1544 }
1545#endif
1546 // dcb/dcz must be decompressed in the parent process. If we reach here
1547 // in the content process with dcb/dcz, the parent failed to handle it.
1548 if (XRE_IsContentProcess()) {
1549 nsAutoCString contentEncoding;
1550 nsresult rv =
1551 mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
1552 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
1553 contentEncoding.LowerCaseEqualsLiteral("dcz"))) {
1554 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"
, 1555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "dcb/dcz Content-Encoding reached the content process"
")"); do { MOZ_CrashSequence(__null, 1555); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1555 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"
, 1555); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "dcb/dcz Content-Encoding reached the content process"
")"); do { MOZ_CrashSequence(__null, 1555); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1556 return NS_ERROR_INVALID_CONTENT_ENCODING;
1557 }
1558 }
1559
1560 if (!LoadApplyConversion()) {
1561 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)
;
1562 return NS_OK;
1563 }
1564
1565 if (LoadHasAppliedConversion()) {
1566 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)
;
1567 return NS_OK;
1568 }
1569
1570 if (LoadDeliveringAltData()) {
1571 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", 1571
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAvailableCachedAltDataType.IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1571); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1572 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)
;
1573 return NS_OK;
1574 }
1575
1576 nsAutoCString contentEncoding;
1577 nsresult rv =
1578 mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
1579 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || contentEncoding.IsEmpty()) return NS_OK;
1580
1581 nsCOMPtr<nsIStreamListener> nextListener =
1582 new InterceptFailedOnStop(aNextListener, this);
1583
1584 // The encodings are listed in the order they were applied
1585 // (see rfc 2616 section 14.11), so they need to removed in reverse
1586 // order. This is accomplished because the converter chain ends up
1587 // being a stack with the last converter created being the first one
1588 // to accept the raw network data.
1589
1590 char* cePtr = contentEncoding.BeginWriting();
1591 uint32_t count = 0;
1592 while (char* val = nsCRT::strtok(cePtr, HTTP_LWS" \t" ",", &cePtr)) {
1593 if (++count > 16) {
1594 // For compatibility with old code, we will just carry on without
1595 // removing the encodings
1596 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)
;
1597 break;
1598 }
1599
1600 if (gHttpHandler->IsAcceptableEncoding(val,
1601 isSecureOrTrustworthyURL(mURI))) {
1602 RefPtr<nsHTTPCompressConv> converter = new nsHTTPCompressConv();
1603 nsAutoCString from(val);
1604 ToLowerCase(from);
1605 rv = converter->AsyncConvertData(from.get(), "uncompressed", nextListener,
1606 aCtxt);
1607 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1608 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)
;
1609 return rv;
1610 }
1611
1612 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)
;
1613 if (Telemetry::CanRecordPrereleaseData()) {
1614 int mode = 0;
1615 if (from.EqualsLiteral("gzip") || from.EqualsLiteral("x-gzip")) {
1616 mode = 1;
1617 } else if (from.EqualsLiteral("deflate") ||
1618 from.EqualsLiteral("x-deflate")) {
1619 mode = 2;
1620 } else if (from.EqualsLiteral("br")) {
1621 mode = 3;
1622 } else if (from.EqualsLiteral("zstd")) {
1623 mode = 4;
1624 } else if (from.EqualsLiteral("dcb")) {
1625 mode = 5;
1626 } else if (from.EqualsLiteral("dcz")) {
1627 mode = 6;
1628 }
1629 glean::http::content_encoding.AccumulateSingleSample(mode);
1630 }
1631#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
1632 if (from.EqualsLiteral("dcb") || from.EqualsLiteral("dcz")) {
1633 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", 1633
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 1633); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1634 }
1635#endif
1636 nextListener = converter;
1637 } else {
1638 if (val) {
1639 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)
;
1640 }
1641 // we *should* return NS_ERROR_UNEXPECTED here, but that will break sites
1642 // that use things like content-encoding: x-gzip, x-gzip (or any other
1643 // weird encoding)
1644 }
1645 }
1646
1647 // dcb and dcz encodings are removed when it's decompressed (always in
1648 // the parent process). However, in theory you could have
1649 // Content-Encoding: dcb,gzip
1650 // in which case we could pass it down to the content process as
1651 // Content-Encoding: gzip. We won't do that; we'll remove all compressors
1652 // if we need to remove any.
1653 // This double compression of course is silly, but supported by the spec.
1654 if (aRemoveEncodings) {
1655 // If we have dcb or dcz, all content-encodings in the header should be
1656 // removed as we're decompressing before the tee in the parent
1657 // process. Also we should remove any encodings if it's a dictionary
1658 // so we can load it quickly
1659 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)
;
1660 // Can't use SetHeader; we need to overwrite the current value
1661 rv = mResponseHead->SetHeaderOverride(nsHttp::Content_Encoding, ""_ns);
Value stored to 'rv' is never read
1662 rv = mResponseHead->SetHeaderOverride(nsHttp::Content_Length, ""_ns);
1663 }
1664 *aNewNextListener = do_AddRef(nextListener).take();
1665 return NS_OK;
1666}
1667
1668NS_IMETHODIMPnsresult
1669HttpBaseChannel::GetContentEncodings(nsIUTF8StringEnumerator** aEncodings) {
1670 if (!mResponseHead) {
1671 *aEncodings = nullptr;
1672 return NS_OK;
1673 }
1674
1675 nsAutoCString encoding;
1676 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, encoding);
1677 if (encoding.IsEmpty()) {
1678 *aEncodings = nullptr;
1679 return NS_OK;
1680 }
1681 RefPtr<nsContentEncodings> enumerator =
1682 new nsContentEncodings(this, encoding.get());
1683 enumerator.forget(aEncodings);
1684 return NS_OK;
1685}
1686
1687//-----------------------------------------------------------------------------
1688// HttpBaseChannel::nsContentEncodings <public>
1689//-----------------------------------------------------------------------------
1690
1691HttpBaseChannel::nsContentEncodings::nsContentEncodings(
1692 nsIHttpChannel* aChannel, const char* aEncodingHeader)
1693 : mEncodingHeader(aEncodingHeader), mChannel(aChannel), mReady(false) {
1694 mCurEnd = aEncodingHeader + strlen(aEncodingHeader);
1695 mCurStart = mCurEnd;
1696}
1697
1698//-----------------------------------------------------------------------------
1699// HttpBaseChannel::nsContentEncodings::nsISimpleEnumerator
1700//-----------------------------------------------------------------------------
1701
1702NS_IMETHODIMPnsresult
1703HttpBaseChannel::nsContentEncodings::HasMore(bool* aMoreEncodings) {
1704 if (mReady) {
1705 *aMoreEncodings = true;
1706 return NS_OK;
1707 }
1708
1709 nsresult rv = PrepareForNext();
1710 *aMoreEncodings = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
1711 return NS_OK;
1712}
1713
1714NS_IMETHODIMPnsresult
1715HttpBaseChannel::nsContentEncodings::GetNext(nsACString& aNextEncoding) {
1716 aNextEncoding.Truncate();
1717 if (!mReady) {
1718 nsresult rv = PrepareForNext();
1719 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1720 return NS_ERROR_FAILURE;
1721 }
1722 }
1723
1724 const nsACString& encoding = Substring(mCurStart, mCurEnd);
1725
1726 nsACString::const_iterator start, end;
1727 encoding.BeginReading(start);
1728 encoding.EndReading(end);
1729
1730 bool haveType = false;
1731 if (CaseInsensitiveFindInReadable("gzip"_ns, start, end)) {
1732 aNextEncoding.AssignLiteral(APPLICATION_GZIP"application/x-gzip");
1733 haveType = true;
1734 }
1735
1736 if (!haveType) {
1737 encoding.BeginReading(start);
1738 if (CaseInsensitiveFindInReadable("compress"_ns, start, end)) {
1739 aNextEncoding.AssignLiteral(APPLICATION_COMPRESS"application/x-compress");
1740 haveType = true;
1741 }
1742 }
1743
1744 if (!haveType) {
1745 encoding.BeginReading(start);
1746 if (CaseInsensitiveFindInReadable("deflate"_ns, start, end)) {
1747 aNextEncoding.AssignLiteral(APPLICATION_ZIP"application/zip");
1748 haveType = true;
1749 }
1750 }
1751
1752 if (!haveType) {
1753 encoding.BeginReading(start);
1754 if (CaseInsensitiveFindInReadable("br"_ns, start, end)) {
1755 aNextEncoding.AssignLiteral(APPLICATION_BROTLI"application/brotli");
1756 haveType = true;
1757 }
1758 }
1759
1760 if (!haveType) {
1761 encoding.BeginReading(start);
1762 if (CaseInsensitiveFindInReadable("zstd"_ns, start, end)) {
1763 aNextEncoding.AssignLiteral(APPLICATION_ZSTD"application/zstd");
1764 haveType = true;
1765 }
1766 }
1767
1768 // Prepare to fetch the next encoding
1769 mCurEnd = mCurStart;
1770 mReady = false;
1771
1772 if (haveType) return NS_OK;
1773
1774 NS_WARNING("Unknown encoding type")NS_DebugBreak(NS_DEBUG_WARNING, "Unknown encoding type", nullptr
, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp", 1774
)
;
1775 return NS_ERROR_FAILURE;
1776}
1777
1778//-----------------------------------------------------------------------------
1779// HttpBaseChannel::nsContentEncodings::nsISupports
1780//-----------------------------------------------------------------------------
1781
1782NS_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"
, 1783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 1783
); __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"
, 1783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel::nsContentEncodings\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1783); __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"
, 1783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1783
); __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"
, 1783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel::nsContentEncodings\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1783); __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", 1783
); 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 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"
, 1783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 1783
); __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"
, 1783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel::nsContentEncodings\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1783); __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"
, 1783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1783
); __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"
, 1783); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"HttpBaseChannel::nsContentEncodings\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 1783); __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", 1783
); 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; }
1784
1785//-----------------------------------------------------------------------------
1786// HttpBaseChannel::nsContentEncodings <private>
1787//-----------------------------------------------------------------------------
1788
1789nsresult HttpBaseChannel::nsContentEncodings::PrepareForNext(void) {
1790 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"
, 1790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurStart == mCurEnd"
") (" "Indeterminate state" ")"); do { MOZ_CrashSequence(__null
, 1790); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1791
1792 // At this point both mCurStart and mCurEnd point to somewhere
1793 // past the end of the next thing we want to return
1794
1795 while (mCurEnd != mEncodingHeader) {
1796 --mCurEnd;
1797 if (*mCurEnd != ',' && !nsCRT::IsAsciiSpace(*mCurEnd)) break;
1798 }
1799 if (mCurEnd == mEncodingHeader) {
1800 return NS_ERROR_NOT_AVAILABLE; // no more encodings
1801 }
1802 ++mCurEnd;
1803
1804 // At this point mCurEnd points to the first char _after_ the
1805 // header we want. Furthermore, mCurEnd - 1 != mEncodingHeader
1806
1807 mCurStart = mCurEnd - 1;
1808 while (mCurStart != mEncodingHeader && *mCurStart != ',' &&
1809 !nsCRT::IsAsciiSpace(*mCurStart)) {
1810 --mCurStart;
1811 }
1812 if (*mCurStart == ',' || nsCRT::IsAsciiSpace(*mCurStart)) {
1813 ++mCurStart; // we stopped because of a weird char, so move up one
1814 }
1815
1816 // At this point mCurStart and mCurEnd bracket the encoding string
1817 // we want. Check that it's not "identity"
1818 if (Substring(mCurStart, mCurEnd)
1819 .Equals("identity", nsCaseInsensitiveCStringComparator)) {
1820 mCurEnd = mCurStart;
1821 return PrepareForNext();
1822 }
1823
1824 mReady = true;
1825 return NS_OK;
1826}
1827
1828//-----------------------------------------------------------------------------
1829// HttpBaseChannel::nsIHttpChannel
1830//-----------------------------------------------------------------------------
1831
1832NS_IMETHODIMPnsresult
1833HttpBaseChannel::GetChannelId(uint64_t* aChannelId) {
1834 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"
, 1834); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1835 *aChannelId = mChannelId;
1836 return NS_OK;
1837}
1838
1839NS_IMETHODIMPnsresult
1840HttpBaseChannel::SetChannelId(uint64_t aChannelId) {
1841 mChannelId = aChannelId;
1842 return NS_OK;
1843}
1844
1845NS_IMETHODIMPnsresult HttpBaseChannel::GetTopLevelContentWindowId(uint64_t* aWindowId) {
1846 if (!mContentWindowId) {
1847 nsCOMPtr<nsILoadContext> loadContext;
1848 GetCallback(loadContext);
1849 if (loadContext) {
1850 nsCOMPtr<mozIDOMWindowProxy> topWindow;
1851 loadContext->GetTopWindow(getter_AddRefs(topWindow));
1852 if (topWindow) {
1853 if (nsPIDOMWindowInner* inner =
1854 nsPIDOMWindowOuter::From(topWindow)->GetCurrentInnerWindow()) {
1855 mContentWindowId = inner->WindowID();
1856 }
1857 }
1858 }
1859 }
1860 *aWindowId = mContentWindowId;
1861 return NS_OK;
1862}
1863
1864NS_IMETHODIMPnsresult HttpBaseChannel::SetBrowserId(uint64_t aId) {
1865 mBrowserId = aId;
1866 return NS_OK;
1867}
1868
1869NS_IMETHODIMPnsresult HttpBaseChannel::GetBrowserId(uint64_t* aId) {
1870 EnsureBrowserId();
1871 *aId = mBrowserId;
1872 return NS_OK;
1873}
1874
1875NS_IMETHODIMPnsresult HttpBaseChannel::SetTopLevelContentWindowId(uint64_t aWindowId) {
1876 mContentWindowId = aWindowId;
1877 return NS_OK;
1878}
1879
1880NS_IMETHODIMPnsresult
1881HttpBaseChannel::IsThirdPartyTrackingResource(bool* aIsTrackingResource) {
1882 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", 1883
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags)"
")"); do { MOZ_CrashSequence(__null, 1883); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1883 !(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", 1883
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mFirstPartyClassificationFlags && mThirdPartyClassificationFlags)"
")"); do { MOZ_CrashSequence(__null, 1883); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1884 *aIsTrackingResource = ChannelClassifierUtils::IsTrackingClassificationFlag(
1885 mThirdPartyClassificationFlags,
1886 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing());
1887 return NS_OK;
1888}
1889
1890NS_IMETHODIMPnsresult
1891HttpBaseChannel::IsThirdPartySocialTrackingResource(
1892 bool* aIsThirdPartySocialTrackingResource) {
1893 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", 1894
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 1894); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1894 !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", 1894
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 1894); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1895 *aIsThirdPartySocialTrackingResource =
1896 ChannelClassifierUtils::IsSocialTrackingClassificationFlag(
1897 mThirdPartyClassificationFlags);
1898 return NS_OK;
1899}
1900
1901NS_IMETHODIMPnsresult
1902HttpBaseChannel::GetClassificationFlags(uint32_t* aFlags) {
1903 if (mThirdPartyClassificationFlags) {
1904 *aFlags = mThirdPartyClassificationFlags;
1905 } else {
1906 *aFlags = mFirstPartyClassificationFlags;
1907 }
1908 return NS_OK;
1909}
1910
1911NS_IMETHODIMPnsresult
1912HttpBaseChannel::GetFirstPartyClassificationFlags(uint32_t* aFlags) {
1913 *aFlags = mFirstPartyClassificationFlags;
1914 return NS_OK;
1915}
1916
1917NS_IMETHODIMPnsresult
1918HttpBaseChannel::GetThirdPartyClassificationFlags(uint32_t* aFlags) {
1919 *aFlags = mThirdPartyClassificationFlags;
1920 return NS_OK;
1921}
1922
1923NS_IMETHODIMPnsresult
1924HttpBaseChannel::GetTransferSize(uint64_t* aTransferSize) {
1925 *aTransferSize = mTransferSize;
1926 return NS_OK;
1927}
1928
1929NS_IMETHODIMPnsresult
1930HttpBaseChannel::GetRequestSize(uint64_t* aRequestSize) {
1931 *aRequestSize = mRequestSize;
1932 return NS_OK;
1933}
1934
1935NS_IMETHODIMPnsresult
1936HttpBaseChannel::GetDecodedBodySize(uint64_t* aDecodedBodySize) {
1937 *aDecodedBodySize = mDecodedBodySize;
1938 return NS_OK;
1939}
1940
1941NS_IMETHODIMPnsresult
1942HttpBaseChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) {
1943 *aEncodedBodySize = mEncodedBodySize;
1944 return NS_OK;
1945}
1946
1947NS_IMETHODIMPnsresult
1948HttpBaseChannel::GetSupportsHTTP3(bool* aSupportsHTTP3) {
1949 *aSupportsHTTP3 = mSupportsHTTP3;
1950 return NS_OK;
1951}
1952
1953NS_IMETHODIMPnsresult
1954HttpBaseChannel::GetHasHTTPSRR(bool* aHasHTTPSRR) {
1955 *aHasHTTPSRR = LoadHasHTTPSRR();
1956 return NS_OK;
1957}
1958
1959NS_IMETHODIMPnsresult
1960HttpBaseChannel::GetRequestMethod(nsACString& aMethod) {
1961 mRequestHead.Method(aMethod);
1962 return NS_OK;
1963}
1964
1965NS_IMETHODIMPnsresult
1966HttpBaseChannel::SetRequestMethod(const nsACString& aMethod) {
1967 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1967); 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"
, 1967, 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"
, 1967); } } 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", 1967
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 1967); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
1968
1969 mLoadInfo->SetIsGETRequest(aMethod.Equals("GET"));
1970
1971 const nsCString& flatMethod = PromiseFlatCStringTPromiseFlatString<char>(aMethod);
1972
1973 // Method names are restricted to valid HTTP tokens.
1974 if (!nsHttp::IsValidToken(flatMethod)) return NS_ERROR_INVALID_ARG;
1975
1976 mRequestHead.SetMethod(flatMethod);
1977 return NS_OK;
1978}
1979
1980NS_IMETHODIMPnsresult
1981HttpBaseChannel::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) {
1982 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"
, 1982); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1983 *aReferrerInfo = do_AddRef(mReferrerInfo).take();
1984 return NS_OK;
1985}
1986
1987nsresult HttpBaseChannel::SetReferrerInfoInternal(
1988 nsIReferrerInfo* aReferrerInfo, bool aClone, bool aCompute,
1989 bool aRespectBeforeConnect) {
1990 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
1992 "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)
1993 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)
;
1994 if (aRespectBeforeConnect) {
1995 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 1995); 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"
, 1995, 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"
, 1995); } } 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", 1995
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 1995); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
1996 }
1997
1998 mReferrerInfo = aReferrerInfo;
1999
2000 // clear existing referrer, if any
2001 nsresult rv = ClearReferrerHeader();
2002 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"
, 2002)
) {
2003 return rv;
2004 }
2005
2006 if (!mReferrerInfo) {
2007 return NS_OK;
2008 }
2009
2010 if (aClone) {
2011 mReferrerInfo = static_cast<dom::ReferrerInfo*>(aReferrerInfo)->Clone();
2012 }
2013
2014 dom::ReferrerInfo* referrerInfo =
2015 static_cast<dom::ReferrerInfo*>(mReferrerInfo.get());
2016
2017 // Don't set referrerInfo if it has not been initialized.
2018 if (!referrerInfo->IsInitialized()) {
2019 mReferrerInfo = nullptr;
2020 return NS_ERROR_NOT_INITIALIZED;
2021 }
2022
2023 if (aCompute) {
2024 rv = referrerInfo->ComputeReferrer(this);
2025 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"
, 2025)
) {
2026 return rv;
2027 }
2028 }
2029
2030 nsCOMPtr<nsIURI> computedReferrer = mReferrerInfo->GetComputedReferrer();
2031 if (!computedReferrer) {
2032 return NS_OK;
2033 }
2034
2035 nsAutoCString spec;
2036 rv = computedReferrer->GetSpec(spec);
2037 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"
, 2037)
) {
2038 return rv;
2039 }
2040
2041 return SetReferrerHeader(spec, aRespectBeforeConnect);
2042}
2043
2044NS_IMETHODIMPnsresult
2045HttpBaseChannel::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
2046 return SetReferrerInfoInternal(aReferrerInfo, true, true, true);
2047}
2048
2049NS_IMETHODIMPnsresult
2050HttpBaseChannel::SetReferrerInfoWithoutClone(nsIReferrerInfo* aReferrerInfo) {
2051 return SetReferrerInfoInternal(aReferrerInfo, false, true, true);
2052}
2053
2054// Return the channel's proxy URI, or if it doesn't exist, the
2055// channel's main URI.
2056NS_IMETHODIMPnsresult
2057HttpBaseChannel::GetProxyURI(nsIURI** aOut) {
2058 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", 2058
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2059 nsCOMPtr<nsIURI> result(mProxyURI);
2060 result.forget(aOut);
2061 return NS_OK;
2062}
2063
2064NS_IMETHODIMPnsresult
2065HttpBaseChannel::GetRequestHeader(const nsACString& aHeader,
2066 nsACString& aValue) {
2067 aValue.Truncate();
2068
2069 // XXX might be better to search the header list directly instead of
2070 // hitting the http atom hash table.
2071 nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
2072 if (!atom) return NS_ERROR_NOT_AVAILABLE;
2073
2074 return mRequestHead.GetHeader(atom, aValue);
2075}
2076
2077NS_IMETHODIMPnsresult
2078HttpBaseChannel::SetRequestHeader(const nsACString& aHeader,
2079 const nsACString& aValue, bool aMerge) {
2080 return SetRequestHeaderInternal(aHeader, aValue, aMerge,
2081 nsHttpHeaderArray::eVarietyRequestOverride);
2082}
2083
2084nsresult HttpBaseChannel::SetRequestHeaderInternal(
2085 const nsACString& aHeader, const nsACString& aValue, bool aMerge,
2086 nsHttpHeaderArray::HeaderVariety aVariety) {
2087 const nsCString& flatHeader = PromiseFlatCStringTPromiseFlatString<char>(aHeader);
2088 const nsCString& flatValue = PromiseFlatCStringTPromiseFlatString<char>(aValue);
2089
2090 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
2092 "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)
2093 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)
;
2094
2095 // Verify header names are valid HTTP tokens and header values are reasonably
2096 // close to whats allowed in RFC 2616.
2097 if (!nsHttp::IsValidToken(flatHeader) ||
2098 !nsHttp::IsReasonableHeaderValue(flatValue)) {
2099 return NS_ERROR_INVALID_ARG;
2100 }
2101
2102 // Mark that the User-Agent header has been modified.
2103 if (nsHttp::ResolveAtom(aHeader) == nsHttp::User_Agent) {
2104 StoreIsUserAgentHeaderModified(true);
2105 }
2106
2107 return mRequestHead.SetHeader(aHeader, flatValue, aMerge, aVariety);
2108}
2109
2110NS_IMETHODIMPnsresult
2111HttpBaseChannel::SetNewReferrerInfo(const nsACString& aUrl,
2112 nsIReferrerInfo::ReferrerPolicyIDL aPolicy,
2113 bool aSendReferrer) {
2114 nsresult rv;
2115 // Create URI from string
2116 nsCOMPtr<nsIURI> aURI;
2117 rv = NS_NewURI(getter_AddRefs(aURI), aUrl);
2118 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"
, 2118); return rv; } } while (false)
;
2119 // Create new ReferrerInfo and initialize it.
2120 nsCOMPtr<nsIReferrerInfo> referrerInfo = new mozilla::dom::ReferrerInfo();
2121 rv = referrerInfo->Init(aPolicy, aSendReferrer, aURI);
2122 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"
, 2122); return rv; } } while (false)
;
2123 // Set ReferrerInfo
2124 return SetReferrerInfo(referrerInfo);
2125}
2126
2127NS_IMETHODIMPnsresult
2128HttpBaseChannel::SetEmptyRequestHeader(const nsACString& aHeader) {
2129 const nsCString& flatHeader = PromiseFlatCStringTPromiseFlatString<char>(aHeader);
2130
2131 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)
2132 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)
;
2133
2134 // Verify header names are valid HTTP tokens and header values are reasonably
2135 // close to whats allowed in RFC 2616.
2136 if (!nsHttp::IsValidToken(flatHeader)) {
2137 return NS_ERROR_INVALID_ARG;
2138 }
2139
2140 // Mark that the User-Agent header has been modified.
2141 if (nsHttp::ResolveAtom(aHeader) == nsHttp::User_Agent) {
2142 StoreIsUserAgentHeaderModified(true);
2143 }
2144
2145 return mRequestHead.SetEmptyHeader(aHeader);
2146}
2147
2148NS_IMETHODIMPnsresult
2149HttpBaseChannel::VisitRequestHeaders(nsIHttpHeaderVisitor* visitor) {
2150 return mRequestHead.VisitHeaders(visitor);
2151}
2152
2153NS_IMETHODIMPnsresult
2154HttpBaseChannel::VisitNonDefaultRequestHeaders(nsIHttpHeaderVisitor* visitor) {
2155 return mRequestHead.VisitHeaders(visitor,
2156 nsHttpHeaderArray::eFilterSkipDefault);
2157}
2158
2159NS_IMETHODIMPnsresult
2160HttpBaseChannel::GetResponseHeader(const nsACString& header,
2161 nsACString& value) {
2162 value.Truncate();
2163
2164 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2165
2166 nsHttpAtom atom = nsHttp::ResolveAtom(header);
2167 if (!atom) return NS_ERROR_NOT_AVAILABLE;
2168
2169 return mResponseHead->GetHeader(atom, value);
2170}
2171
2172NS_IMETHODIMPnsresult
2173HttpBaseChannel::SetResponseHeader(const nsACString& header,
2174 const nsACString& value, bool merge) {
2175 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
2177 "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)
2178 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)
2179 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)
;
2180
2181 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2182
2183 nsHttpAtom atom = nsHttp::ResolveAtom(header);
2184 if (!atom) return NS_ERROR_NOT_AVAILABLE;
2185
2186 // these response headers must not be changed
2187 if (atom == nsHttp::Content_Type || atom == nsHttp::Content_Length ||
2188 atom == nsHttp::Content_Encoding || atom == nsHttp::Trailer ||
2189 atom == nsHttp::Transfer_Encoding) {
2190 return NS_ERROR_ILLEGAL_VALUE;
2191 }
2192
2193 StoreResponseHeadersModified(true);
2194
2195 return mResponseHead->SetHeader(header, value, merge);
2196}
2197
2198NS_IMETHODIMPnsresult
2199HttpBaseChannel::VisitResponseHeaders(nsIHttpHeaderVisitor* visitor) {
2200 if (!mResponseHead) {
2201 return NS_ERROR_NOT_AVAILABLE;
2202 }
2203 return mResponseHead->VisitHeaders(visitor,
2204 nsHttpHeaderArray::eFilterResponse);
2205}
2206
2207NS_IMETHODIMPnsresult
2208HttpBaseChannel::GetOriginalResponseHeader(const nsACString& aHeader,
2209 nsIHttpHeaderVisitor* aVisitor) {
2210 if (!mResponseHead) {
2211 return NS_ERROR_NOT_AVAILABLE;
2212 }
2213
2214 nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
2215 if (!atom) {
2216 return NS_ERROR_NOT_AVAILABLE;
2217 }
2218
2219 return mResponseHead->GetOriginalHeader(atom, aVisitor);
2220}
2221
2222NS_IMETHODIMPnsresult
2223HttpBaseChannel::VisitOriginalResponseHeaders(nsIHttpHeaderVisitor* aVisitor) {
2224 if (!mResponseHead) {
2225 return NS_ERROR_NOT_AVAILABLE;
2226 }
2227
2228 return mResponseHead->VisitHeaders(
2229 aVisitor, nsHttpHeaderArray::eFilterResponseOriginal);
2230}
2231
2232NS_IMETHODIMPnsresult
2233HttpBaseChannel::GetAllowSTS(bool* value) {
2234 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", 2234
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2235 *value = LoadAllowSTS();
2236 return NS_OK;
2237}
2238
2239NS_IMETHODIMPnsresult
2240HttpBaseChannel::SetAllowSTS(bool value) {
2241 // This controls whether the parent process honors HSTS for this channel, so
2242 // it must not be settable from a content process.
2243 if (!XRE_IsParentProcess()) {
2244 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"
, 2244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value == true"
") (" "allowSTS = false is parent process only" ")"); do { MOZ_CrashSequence
(__null, 2244); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2245 return NS_OK;
2246 }
2247 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2247); 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"
, 2247, 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"
, 2247); } } 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", 2247
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 2247); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
2248 StoreAllowSTS(value);
2249 return NS_OK;
2250}
2251
2252NS_IMETHODIMPnsresult
2253HttpBaseChannel::GetIsOCSP(bool* value) {
2254 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", 2254
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2255 *value = LoadIsOCSP();
2256 return NS_OK;
2257}
2258
2259NS_IMETHODIMPnsresult
2260HttpBaseChannel::SetIsOCSP(bool value) {
2261 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2261); 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"
, 2261, 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"
, 2261); } } 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", 2261
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 2261); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
2262 StoreIsOCSP(value);
2263 return NS_OK;
2264}
2265
2266NS_IMETHODIMPnsresult
2267HttpBaseChannel::GetIsUserAgentHeaderModified(bool* value) {
2268 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", 2268
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2269 *value = LoadIsUserAgentHeaderModified();
2270 return NS_OK;
2271}
2272
2273NS_IMETHODIMPnsresult
2274HttpBaseChannel::SetIsUserAgentHeaderModified(bool value) {
2275 StoreIsUserAgentHeaderModified(value);
2276 return NS_OK;
2277}
2278
2279NS_IMETHODIMPnsresult
2280HttpBaseChannel::GetRedirectionLimit(uint32_t* value) {
2281 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", 2281
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2282 *value = mRedirectionLimit;
2283 return NS_OK;
2284}
2285
2286NS_IMETHODIMPnsresult
2287HttpBaseChannel::SetRedirectionLimit(uint32_t value) {
2288 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2288); 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"
, 2288, 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"
, 2288); } } 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", 2288
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 2288); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
2289
2290 mRedirectionLimit = std::min<uint32_t>(value, 0xff);
2291 return NS_OK;
2292}
2293
2294nsresult HttpBaseChannel::OverrideSecurityInfo(
2295 nsITransportSecurityInfo* aSecurityInfo) {
2296 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"
, 2298); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mSecurityInfo"
") (" "This can only be called when we don't have a security info "
"object already" ")"); do { MOZ_CrashSequence(__null, 2298);
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2297 "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"
, 2298); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mSecurityInfo"
") (" "This can only be called when we don't have a security info "
"object already" ")"); do { MOZ_CrashSequence(__null, 2298);
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2298 "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"
, 2298); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mSecurityInfo"
") (" "This can only be called when we don't have a security info "
"object already" ")"); do { MOZ_CrashSequence(__null, 2298);
__attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
2299 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", 2301
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aSecurityInfo"
") (" "This can only be called with a valid security info object"
")"); do { MOZ_CrashSequence(__null, 2301); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2300 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", 2301
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aSecurityInfo"
") (" "This can only be called with a valid security info object"
")"); do { MOZ_CrashSequence(__null, 2301); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2301 "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", 2301
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aSecurityInfo"
") (" "This can only be called with a valid security info object"
")"); do { MOZ_CrashSequence(__null, 2301); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2302 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"
, 2304); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
") (" "This can only be called on channels that are not bypassing "
"interception" ")"); do { MOZ_CrashSequence(__null, 2304); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2303 "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"
, 2304); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
") (" "This can only be called on channels that are not bypassing "
"interception" ")"); do { MOZ_CrashSequence(__null, 2304); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2304 "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"
, 2304); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
") (" "This can only be called on channels that are not bypassing "
"interception" ")"); do { MOZ_CrashSequence(__null, 2304); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
2305 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"
, 2306); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadResponseCouldBeSynthesized()"
") (" "This can only be called on channels that can be intercepted"
")"); do { MOZ_CrashSequence(__null, 2306); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2306 "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"
, 2306); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadResponseCouldBeSynthesized()"
") (" "This can only be called on channels that can be intercepted"
")"); do { MOZ_CrashSequence(__null, 2306); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2307 if (mSecurityInfo) {
2308 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
2310 "[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)
2311 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
2312 return NS_ERROR_UNEXPECTED;
2313 }
2314 if (!LoadResponseCouldBeSynthesized()) {
2315 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
2317 "[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)
2318 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
2319 return NS_ERROR_UNEXPECTED;
2320 }
2321
2322 mSecurityInfo = aSecurityInfo;
2323 return NS_OK;
2324}
2325
2326NS_IMETHODIMPnsresult
2327HttpBaseChannel::IsNoStoreResponse(bool* value) {
2328 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2329 *value = mResponseHead->NoStore();
2330 return NS_OK;
2331}
2332
2333NS_IMETHODIMPnsresult
2334HttpBaseChannel::IsNoCacheResponse(bool* value) {
2335 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2336 *value = mResponseHead->NoCache();
2337 if (!*value) *value = mResponseHead->ExpiresInPast();
2338 return NS_OK;
2339}
2340
2341NS_IMETHODIMPnsresult
2342HttpBaseChannel::GetResponseStatus(uint32_t* aValue) {
2343 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2344 *aValue = mResponseHead->Status();
2345 return NS_OK;
2346}
2347
2348NS_IMETHODIMPnsresult
2349HttpBaseChannel::GetResponseStatusText(nsACString& aValue) {
2350 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2351 nsAutoCString version;
2352 // https://fetch.spec.whatwg.org :
2353 // Responses over an HTTP/2 connection will always have the empty byte
2354 // sequence as status message as HTTP/2 does not support them.
2355 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"
, 2355)
||
2356 !version.EqualsLiteral("h2")) {
2357 mResponseHead->StatusText(aValue);
2358 }
2359 return NS_OK;
2360}
2361
2362NS_IMETHODIMPnsresult
2363HttpBaseChannel::GetRequestSucceeded(bool* aValue) {
2364 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
2365 uint32_t status = mResponseHead->Status();
2366 *aValue = (status / 100 == 2);
2367 return NS_OK;
2368}
2369
2370NS_IMETHODIMPnsresult
2371HttpBaseChannel::RedirectTo(nsIURI* targetURI) {
2372 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", 2372
); return NS_ERROR_INVALID_ARG; } } while (false)
;
2373
2374 nsAutoCString spec;
2375 targetURI->GetAsciiSpec(spec);
2376 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)
;
2377 LogCallingScriptLocation(this);
2378
2379 // We cannot redirect after OnStartRequest of the listener
2380 // has been called, since to redirect we have to switch channels
2381 // and the dance with OnStartRequest et al has to start over.
2382 // This would break the nsIStreamListener contract.
2383 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"
, 2383); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
2384
2385 // The first parameter is the URI we would like to redirect to
2386 // The second parameter should default to false if normal redirect
2387 mAPIRedirectTo =
2388 Some(mozilla::MakeCompactPair(nsCOMPtr<nsIURI>(targetURI), false));
2389
2390 // Only Web Extensions are allowed to redirect a channel to a data:
2391 // URI. To avoid any bypasses after the channel was flagged by
2392 // the WebRequst API, we are dropping the flag here.
2393 mLoadInfo->SetAllowInsecureRedirectToDataURI(false);
2394
2395 // We may want to rewrite origin allowance, hence we need an
2396 // artificial response head.
2397 if (!mResponseHead) {
2398 mResponseHead = std::make_unique<nsHttpResponseHead>();
2399 }
2400 return NS_OK;
2401}
2402
2403NS_IMETHODIMPnsresult
2404HttpBaseChannel::TransparentRedirectTo(nsIURI* targetURI) {
2405 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)
;
2406 RedirectTo(targetURI);
2407 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"
, 2407); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo"
") (" "How did this happen?" ")"); do { MOZ_CrashSequence(__null
, 2407); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
2408 mAPIRedirectTo->second() = true;
2409 return NS_OK;
2410}
2411
2412NS_IMETHODIMPnsresult
2413HttpBaseChannel::UpgradeToSecure() {
2414 // Upgrades are handled internally between http-on-modify-request and
2415 // http-on-before-connect, which means upgrades are only possible during
2416 // on-modify, or WebRequest.onBeforeRequest in Web Extensions. Once we are
2417 // past the code path where upgrades are handled, attempting an upgrade
2418 // will throw an error.
2419 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"
, 2419); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
2420
2421 StoreUpgradeToSecure(true);
2422 // todo: Currently UpgradeToSecure() is called only by web extensions, if
2423 // that ever changes, we need to update the following telemetry collection
2424 // to reflect any future changes.
2425 mLoadInfo->SetHttpsUpgradeTelemetry(nsILoadInfo::WEB_EXTENSION_UPGRADE);
2426
2427 return NS_OK;
2428}
2429
2430NS_IMETHODIMPnsresult
2431HttpBaseChannel::GetRequestObserversCalled(bool* aCalled) {
2432 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", 2432
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2433 *aCalled = LoadRequestObserversCalled();
2434 return NS_OK;
2435}
2436
2437NS_IMETHODIMPnsresult
2438HttpBaseChannel::SetRequestObserversCalled(bool aCalled) {
2439 StoreRequestObserversCalled(aCalled);
2440 return NS_OK;
2441}
2442
2443NS_IMETHODIMPnsresult
2444HttpBaseChannel::GetRequestContextID(uint64_t* aRCID) {
2445 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", 2445
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2446 *aRCID = mRequestContextID;
2447 return NS_OK;
2448}
2449
2450NS_IMETHODIMPnsresult
2451HttpBaseChannel::SetRequestContextID(uint64_t aRCID) {
2452 mRequestContextID = aRCID;
2453 return NS_OK;
2454}
2455
2456NS_IMETHODIMPnsresult
2457HttpBaseChannel::GetIsMainDocumentChannel(bool* aValue) {
2458 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", 2458
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2459 *aValue = IsNavigation();
2460 return NS_OK;
2461}
2462
2463NS_IMETHODIMPnsresult
2464HttpBaseChannel::SetIsMainDocumentChannel(bool aValue) {
2465 StoreForceMainDocumentChannel(aValue);
2466 return NS_OK;
2467}
2468
2469NS_IMETHODIMPnsresult
2470HttpBaseChannel::GetIsUserAgentHeaderOutdated(bool* aValue) {
2471 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", 2471
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2472 *aValue = LoadIsUserAgentHeaderOutdated();
2473 return NS_OK;
2474}
2475
2476NS_IMETHODIMPnsresult
2477HttpBaseChannel::SetIsUserAgentHeaderOutdated(bool aValue) {
2478 StoreIsUserAgentHeaderOutdated(aValue);
2479 return NS_OK;
2480}
2481
2482NS_IMETHODIMPnsresult
2483HttpBaseChannel::GetProtocolVersion(nsACString& aProtocolVersion) {
2484 // Try to use ALPN if available and if it is not for a proxy, i.e if an
2485 // https proxy was not used or if https proxy was used but the connection to
2486 // the origin server is also https. In the case, an https proxy was used and
2487 // the connection to the origin server was http, mSecurityInfo will be from
2488 // the proxy.
2489 if (!mConnectionInfo || !mConnectionInfo->UsingHttpsProxy() ||
2490 mConnectionInfo->EndToEndSSL()) {
2491 nsAutoCString protocol;
2492 if (mSecurityInfo &&
2493 NS_SUCCEEDED(mSecurityInfo->GetNegotiatedNPN(protocol))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mSecurityInfo->
GetNegotiatedNPN(protocol))), 1)))
&&
2494 !protocol.IsEmpty()) {
2495 // The negotiated protocol was not empty so we can use it.
2496 aProtocolVersion = std::move(protocol);
2497 return NS_OK;
2498 }
2499 }
2500
2501 if (mResponseHead) {
2502 HttpVersion version = mResponseHead->Version();
2503 aProtocolVersion.Assign(nsHttp::GetProtocolVersion(version));
2504 return NS_OK;
2505 }
2506
2507 return NS_ERROR_NOT_AVAILABLE;
2508}
2509
2510//-----------------------------------------------------------------------------
2511// HttpBaseChannel::nsIHttpChannelInternal
2512//-----------------------------------------------------------------------------
2513
2514NS_IMETHODIMPnsresult
2515HttpBaseChannel::SetTopWindowURIIfUnknown(nsIURI* aTopWindowURI) {
2516 if (!aTopWindowURI) {
2517 return NS_ERROR_INVALID_ARG;
2518 }
2519
2520 if (mTopWindowURI) {
2521 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
2523 "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)
2524 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
2525 return NS_ERROR_FAILURE;
2526 }
2527
2528 nsCOMPtr<nsIURI> topWindowURI;
2529 (void)GetTopWindowURI(getter_AddRefs(topWindowURI));
2530
2531 // Don't modify |mTopWindowURI| if we can get one from GetTopWindowURI().
2532 if (topWindowURI) {
2533 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
2535 "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)
2536 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
2537 return NS_ERROR_FAILURE;
2538 }
2539
2540 mTopWindowURI = aTopWindowURI;
2541 return NS_OK;
2542}
2543
2544NS_IMETHODIMPnsresult
2545HttpBaseChannel::GetTopWindowURI(nsIURI** aTopWindowURI) {
2546 nsCOMPtr<nsIURI> uriBeingLoaded =
2547 AntiTrackingUtils::MaybeGetDocumentURIBeingLoaded(this);
2548 return GetTopWindowURI(uriBeingLoaded, aTopWindowURI);
2549}
2550
2551nsresult HttpBaseChannel::GetTopWindowURI(nsIURI* aURIBeingLoaded,
2552 nsIURI** aTopWindowURI) {
2553 nsresult rv = NS_OK;
2554 nsCOMPtr<mozIThirdPartyUtil> util;
2555 // Only compute the top window URI once. In e10s, this must be computed in the
2556 // child. The parent gets the top window URI through HttpChannelOpenArgs.
2557 if (!mTopWindowURI) {
2558 util = components::ThirdPartyUtil::Service();
2559 if (!util) {
2560 return NS_ERROR_NOT_AVAILABLE;
2561 }
2562 nsCOMPtr<mozIDOMWindowProxy> win;
2563 rv = util->GetTopWindowForChannel(this, aURIBeingLoaded,
2564 getter_AddRefs(win));
2565 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2566 rv = util->GetURIFromWindow(win, getter_AddRefs(mTopWindowURI));
2567#if DEBUG1
2568 if (mTopWindowURI) {
2569 nsCString spec;
2570 if (NS_SUCCEEDED(mTopWindowURI->GetSpec(spec))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mTopWindowURI->
GetSpec(spec))), 1)))
) {
2571 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)
2572 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)
;
2573 }
2574 }
2575#endif
2576 }
2577 }
2578 *aTopWindowURI = do_AddRef(mTopWindowURI).take();
2579 return rv;
2580}
2581
2582NS_IMETHODIMPnsresult
2583HttpBaseChannel::GetDocumentURI(nsIURI** aDocumentURI) {
2584 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"
, 2584); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2585 *aDocumentURI = do_AddRef(mDocumentURI).take();
2586 return NS_OK;
2587}
2588
2589NS_IMETHODIMPnsresult
2590HttpBaseChannel::SetDocumentURI(nsIURI* aDocumentURI) {
2591 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 2591); 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"
, 2591, 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"
, 2591); } } 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", 2591
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 2591); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
2592 mDocumentURI = aDocumentURI;
2593 return NS_OK;
2594}
2595
2596NS_IMETHODIMPnsresult
2597HttpBaseChannel::GetRequestVersion(uint32_t* major, uint32_t* minor) {
2598 HttpVersion version = mRequestHead.Version();
2599
2600 if (major) {
2601 *major = static_cast<uint32_t>(version) / 10;
2602 }
2603 if (minor) {
2604 *minor = static_cast<uint32_t>(version) % 10;
2605 }
2606
2607 return NS_OK;
2608}
2609
2610NS_IMETHODIMPnsresult
2611HttpBaseChannel::GetResponseVersion(uint32_t* major, uint32_t* minor) {
2612 if (!mResponseHead) {
2613 *major = *minor = 0; // we should at least be kind about it
2614 return NS_ERROR_NOT_AVAILABLE;
2615 }
2616
2617 HttpVersion version = mResponseHead->Version();
2618
2619 if (major) {
2620 *major = static_cast<uint32_t>(version) / 10;
2621 }
2622 if (minor) {
2623 *minor = static_cast<uint32_t>(version) % 10;
2624 }
2625
2626 return NS_OK;
2627}
2628
2629bool HttpBaseChannel::IsBrowsingContextDiscarded() const {
2630 // If there is no loadGroup attached to the current channel, we check the
2631 // global private browsing state for the private channel instead. For
2632 // non-private channel, we will always return false here.
2633 //
2634 // Note that we can only access the global private browsing state in the
2635 // parent process. So, we will fallback to just return false in the content
2636 // process.
2637 if (!mLoadGroup) {
2638 if (!XRE_IsParentProcess()) {
2639 return false;
2640 }
2641
2642 return mLoadInfo->GetOriginAttributes().IsPrivateBrowsing() &&
2643 !dom::CanonicalBrowsingContext::IsPrivateBrowsingActive();
2644 }
2645
2646 return mLoadGroup->GetIsBrowsingContextDiscarded();
2647}
2648
2649// https://mikewest.github.io/corpp/#process-navigation-response
2650nsresult HttpBaseChannel::ProcessCrossOriginEmbedderPolicyHeader() {
2651 nsresult rv;
2652 if (!StaticPrefs::browser_tabs_remote_useCrossOriginEmbedderPolicy()) {
2653 return NS_OK;
2654 }
2655
2656 // Only consider Cross-Origin-Embedder-Policy for document loads.
2657 if (mLoadInfo->GetExternalContentPolicyType() !=
2658 ExtContentPolicy::TYPE_DOCUMENT &&
2659 mLoadInfo->GetExternalContentPolicyType() !=
2660 ExtContentPolicy::TYPE_SUBDOCUMENT) {
2661 return NS_OK;
2662 }
2663
2664 nsILoadInfo::CrossOriginEmbedderPolicy resultPolicy =
2665 nsILoadInfo::EMBEDDER_POLICY_NULL;
2666 bool isCoepCredentiallessEnabled;
2667 rv = mLoadInfo->GetIsOriginTrialCoepCredentiallessEnabledForTopLevel(
2668 &isCoepCredentiallessEnabled);
2669 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"
, 2669); return rv; } } while (false)
;
2670 rv = GetResponseEmbedderPolicy(isCoepCredentiallessEnabled, &resultPolicy);
2671 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2672 return NS_OK;
2673 }
2674
2675 // https://html.spec.whatwg.org/multipage/origin.html#coep
2676 if (mLoadInfo->GetExternalContentPolicyType() ==
2677 ExtContentPolicy::TYPE_SUBDOCUMENT &&
2678 !nsHttpChannel::IsRedirectStatus(mResponseHead->Status()) &&
2679 mLoadInfo->GetLoadingEmbedderPolicy() !=
2680 nsILoadInfo::EMBEDDER_POLICY_NULL &&
2681 resultPolicy != nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP &&
2682 resultPolicy != nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS) {
2683 return NS_ERROR_DOM_COEP_FAILED;
2684 }
2685
2686 return NS_OK;
2687}
2688
2689// https://mikewest.github.io/corpp/#corp-check
2690nsresult HttpBaseChannel::ProcessCrossOriginResourcePolicyHeader() {
2691 // Fetch 4.5.9
2692 dom::RequestMode requestMode;
2693 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", 2693
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(GetRequestMode(&requestMode))"
")"); do { MOZ_CrashSequence(__null, 2693); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2694 // XXX this seems wrong per spec? What about navigate
2695 if (requestMode != RequestMode::No_cors) {
2696 return NS_OK;
2697 }
2698
2699 // We only apply this for resources.
2700 auto extContentPolicyType = mLoadInfo->GetExternalContentPolicyType();
2701 if (extContentPolicyType == ExtContentPolicy::TYPE_DOCUMENT ||
2702 extContentPolicyType == ExtContentPolicy::TYPE_WEBSOCKET ||
2703 extContentPolicyType == ExtContentPolicy::TYPE_SAVEAS_DOWNLOAD) {
2704 return NS_OK;
2705 }
2706
2707 if (extContentPolicyType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
2708 // COEP pref off, skip CORP checking for subdocument.
2709 if (!StaticPrefs::browser_tabs_remote_useCrossOriginEmbedderPolicy()) {
2710 return NS_OK;
2711 }
2712 // COEP 3.2.1.2 when request targets a nested browsing context then embedder
2713 // policy value is "unsafe-none", then return allowed.
2714 if (mLoadInfo->GetLoadingEmbedderPolicy() ==
2715 nsILoadInfo::EMBEDDER_POLICY_NULL) {
2716 return NS_OK;
2717 }
2718 }
2719
2720 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"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetLoadingPrincipal()"
") (" "Resources should always have a LoadingPrincipal" ")")
; do { MOZ_CrashSequence(__null, 2721); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2721 "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"
, 2721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetLoadingPrincipal()"
") (" "Resources should always have a LoadingPrincipal" ")")
; do { MOZ_CrashSequence(__null, 2721); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2722 if (!mResponseHead) {
2723 return NS_OK;
2724 }
2725
2726 if (mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal()) {
2727 return NS_OK;
2728 }
2729
2730 nsAutoCString content;
2731 (void)mResponseHead->GetHeader(nsHttp::Cross_Origin_Resource_Policy, content);
2732
2733 if (StaticPrefs::browser_tabs_remote_useCrossOriginEmbedderPolicy()) {
2734 if (content.IsEmpty()) {
2735 if (mLoadInfo->GetLoadingEmbedderPolicy() ==
2736 nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS) {
2737 bool requestIncludesCredentials = false;
2738 nsresult rv = GetCorsIncludeCredentials(&requestIncludesCredentials);
2739 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2740 return NS_OK;
2741 }
2742 // COEP: Set policy to `same-origin` if: response’s
2743 // request-includes-credentials is true, or forNavigation is true.
2744 if (requestIncludesCredentials ||
2745 extContentPolicyType == ExtContentPolicyType::TYPE_SUBDOCUMENT) {
2746 content = "same-origin"_ns;
2747 }
2748 } else if (mLoadInfo->GetLoadingEmbedderPolicy() ==
2749 nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP) {
2750 // COEP 3.2.1.6 If policy is null, and embedder policy is
2751 // "require-corp", set policy to "same-origin". Note that we treat
2752 // invalid value as "cross-origin", which spec indicates. We might want
2753 // to make that stricter.
2754 content = "same-origin"_ns;
2755 }
2756 }
2757 }
2758
2759 if (content.IsEmpty()) {
2760 return NS_OK;
2761 }
2762
2763 nsCOMPtr<nsIPrincipal> channelOrigin;
2764 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
2765 this, getter_AddRefs(channelOrigin));
2766
2767 // Cross-Origin-Resource-Policy = %s"same-origin" / %s"same-site" /
2768 // %s"cross-origin"
2769 if (content.EqualsLiteral("same-origin")) {
2770 if (!channelOrigin->Equals(mLoadInfo->GetLoadingPrincipal())) {
2771 return NS_ERROR_DOM_CORP_FAILED;
2772 }
2773 return NS_OK;
2774 }
2775 if (content.EqualsLiteral("same-site")) {
2776 nsAutoCString documentBaseDomain;
2777 nsAutoCString resourceBaseDomain;
2778 mLoadInfo->GetLoadingPrincipal()->GetBaseDomain(documentBaseDomain);
2779 channelOrigin->GetBaseDomain(resourceBaseDomain);
2780 if (documentBaseDomain != resourceBaseDomain) {
2781 return NS_ERROR_DOM_CORP_FAILED;
2782 }
2783
2784 nsCOMPtr<nsIURI> resourceURI = channelOrigin->GetURI();
2785 if (!mLoadInfo->GetLoadingPrincipal()->SchemeIs("https") &&
2786 resourceURI->SchemeIs("https")) {
2787 return NS_ERROR_DOM_CORP_FAILED;
2788 }
2789
2790 return NS_OK;
2791 }
2792
2793 return NS_OK;
2794}
2795
2796// See https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
2797// This method runs steps 1-4 of the algorithm to compare
2798// cross-origin-opener policies
2799static bool CompareCrossOriginOpenerPolicies(
2800 nsILoadInfo::CrossOriginOpenerPolicy documentPolicy,
2801 nsIPrincipal* documentOrigin,
2802 nsILoadInfo::CrossOriginOpenerPolicy resultPolicy,
2803 nsIPrincipal* resultOrigin) {
2804 if (documentPolicy == nsILoadInfo::OPENER_POLICY_UNSAFE_NONE &&
2805 resultPolicy == nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) {
2806 return true;
2807 }
2808
2809 if (documentPolicy == nsILoadInfo::OPENER_POLICY_UNSAFE_NONE ||
2810 resultPolicy == nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) {
2811 return false;
2812 }
2813
2814 if (documentPolicy == resultPolicy && documentOrigin->Equals(resultOrigin)) {
2815 return true;
2816 }
2817
2818 return false;
2819}
2820
2821// This runs steps 1-5 of the algorithm when navigating a top level document.
2822// See https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
2823nsresult HttpBaseChannel::ComputeCrossOriginOpenerPolicyMismatch() {
2824 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", 2824
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 2824); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2825
2826 StoreHasCrossOriginOpenerPolicyMismatch(false);
2827 if (!StaticPrefs::browser_tabs_remote_useCrossOriginOpenerPolicy()) {
2828 return NS_OK;
2829 }
2830
2831 // Only consider Cross-Origin-Opener-Policy for toplevel document loads.
2832 if (mLoadInfo->GetExternalContentPolicyType() !=
2833 ExtContentPolicy::TYPE_DOCUMENT) {
2834 return NS_OK;
2835 }
2836
2837 // Maybe the channel failed and we have no response head?
2838 if (!mResponseHead) {
2839 // Not having a response head is not a hard failure at the point where
2840 // this method is called.
2841 return NS_OK;
2842 }
2843
2844 RefPtr<mozilla::dom::BrowsingContext> ctx;
2845 mLoadInfo->GetBrowsingContext(getter_AddRefs(ctx));
2846
2847 // In xpcshell-tests we don't always have a browsingContext
2848 if (!ctx) {
2849 return NS_OK;
2850 }
2851
2852 nsCOMPtr<nsIPrincipal> resultOrigin;
2853 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
2854 this, getter_AddRefs(resultOrigin));
2855
2856 // Get the policy of the active document, and the policy for the result.
2857 nsILoadInfo::CrossOriginOpenerPolicy documentPolicy = ctx->GetOpenerPolicy();
2858 nsILoadInfo::CrossOriginOpenerPolicy resultPolicy =
2859 nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
2860 (void)ComputeCrossOriginOpenerPolicy(documentPolicy, &resultPolicy);
2861 mComputedCrossOriginOpenerPolicy = resultPolicy;
2862
2863 // Add a permission to mark this site as high-value into the permission DB.
2864 if (resultPolicy != nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) {
2865 mozilla::dom::AddHighValuePermission(
2866 resultOrigin, mozilla::dom::kHighValueCOOPPermission);
2867 }
2868
2869 // If bc's popup sandboxing flag set is not empty and potentialCOOP is
2870 // non-null, then navigate bc to a network error and abort these steps.
2871 if (resultPolicy != nsILoadInfo::OPENER_POLICY_UNSAFE_NONE &&
2872 mLoadInfo->GetSandboxFlags()) {
2873 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 "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)
2875 "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)
;
2876 return NS_ERROR_DOM_COOP_FAILED;
2877 }
2878
2879 // In xpcshell-tests we don't always have a current window global
2880 RefPtr<mozilla::dom::WindowGlobalParent> currentWindowGlobal =
2881 ctx->Canonical()->GetCurrentWindowGlobal();
2882 if (!currentWindowGlobal) {
2883 return NS_OK;
2884 }
2885
2886 // We use the top window principal as the documentOrigin
2887 nsCOMPtr<nsIPrincipal> documentOrigin =
2888 currentWindowGlobal->DocumentPrincipal();
2889
2890 bool compareResult = CompareCrossOriginOpenerPolicies(
2891 documentPolicy, documentOrigin, resultPolicy, resultOrigin);
2892
2893 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
2894 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 ("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)
2896 "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)
2897 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)
;
2898 nsAutoCString docOrigin("(null)");
2899 nsCOMPtr<nsIURI> uri = documentOrigin->GetURI();
2900 if (uri) {
2901 uri->GetSpec(docOrigin);
2902 }
2903 nsAutoCString resOrigin("(null)");
2904 uri = resultOrigin->GetURI();
2905 if (uri) {
2906 uri->GetSpec(resOrigin);
2907 }
2908 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)
;
2909 }
2910
2911 if (compareResult) {
2912 return NS_OK;
2913 }
2914
2915 // If one of the following is false:
2916 // - document's policy is same-origin-allow-popups
2917 // - resultPolicy is null
2918 // - doc is the initial about:blank document
2919 // then we have a mismatch.
2920
2921 if (documentPolicy != nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_ALLOW_POPUPS) {
2922 StoreHasCrossOriginOpenerPolicyMismatch(true);
2923 return NS_OK;
2924 }
2925
2926 if (resultPolicy != nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) {
2927 StoreHasCrossOriginOpenerPolicyMismatch(true);
2928 return NS_OK;
2929 }
2930
2931 if (!currentWindowGlobal->IsInitialDocument()) {
2932 StoreHasCrossOriginOpenerPolicyMismatch(true);
2933 return NS_OK;
2934 }
2935
2936 return NS_OK;
2937}
2938
2939nsresult HttpBaseChannel::ProcessCrossOriginSecurityHeaders() {
2940 StoreProcessCrossOriginSecurityHeadersCalled(true);
2941 nsresult rv = ProcessCrossOriginEmbedderPolicyHeader();
2942 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2943 return rv;
2944 }
2945 rv = ProcessCrossOriginResourcePolicyHeader();
2946 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2947 return rv;
2948 }
2949 return ComputeCrossOriginOpenerPolicyMismatch();
2950}
2951
2952enum class Report { Error, Warning };
2953
2954// Helper Function to report messages to the console when the loaded
2955// script had a wrong MIME type.
2956void ReportMimeTypeMismatch(HttpBaseChannel* aChannel, const char* aMessageName,
2957 nsIURI* aURI, const nsACString& aContentType,
2958 Report report) {
2959 NS_ConvertUTF8toUTF16 spec(aURI->GetSpecOrDefault());
2960 NS_ConvertUTF8toUTF16 contentType(aContentType);
2961
2962 aChannel->LogMimeTypeMismatch(nsCString(aMessageName),
2963 report == Report::Warning, spec, contentType);
2964}
2965
2966// Check and potentially enforce X-Content-Type-Options: nosniff
2967nsresult ProcessXCTO(HttpBaseChannel* aChannel, nsIURI* aURI,
2968 nsHttpResponseHead* aResponseHead,
2969 nsILoadInfo* aLoadInfo) {
2970 if (!aURI || !aResponseHead || !aLoadInfo) {
2971 // if there is no uri, no response head or no loadInfo, then there is
2972 // nothing to do
2973 return NS_OK;
2974 }
2975
2976 // 1) Query the XCTO header and check if 'nosniff' is the first value.
2977 nsAutoCString contentTypeOptionsHeader;
2978 if (!aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader)) {
2979 // if failed to get XCTO header, then there is nothing to do.
2980 return NS_OK;
2981 }
2982
2983 // let's compare the header (ignoring case)
2984 // e.g. "NoSniFF" -> "nosniff"
2985 // if it's not 'nosniff' then there is nothing to do here
2986 if (!contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) {
2987 // since we are getting here, the XCTO header was sent;
2988 // a non matching value most likely means a mistake happenend;
2989 // e.g. sending 'nosnif' instead of 'nosniff', let's log a warning.
2990 AutoTArray<nsString, 1> params;
2991 CopyUTF8toUTF16(contentTypeOptionsHeader, *params.AppendElement());
2992 RefPtr<dom::Document> doc;
2993 aLoadInfo->GetLoadingDocument(getter_AddRefs(doc));
2994 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "XCTO"_ns, doc,
2995 PropertiesFile::SECURITY_PROPERTIES,
2996 "XCTOHeaderValueMissing", params);
2997 return NS_OK;
2998 }
2999
3000 // 2) Query the content type from the channel
3001 nsAutoCString contentType;
3002 aResponseHead->ContentType(contentType);
3003
3004 // 3) Compare the expected MIME type with the actual type
3005 if (aLoadInfo->GetExternalContentPolicyType() ==
3006 ExtContentPolicy::TYPE_STYLESHEET) {
3007 if (contentType.EqualsLiteral(TEXT_CSS"text/css")) {
3008 return NS_OK;
3009 }
3010 ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType,
3011 Report::Error);
3012 return NS_ERROR_CORRUPTED_CONTENT;
3013 }
3014
3015 if (aLoadInfo->GetExternalContentPolicyType() ==
3016 ExtContentPolicy::TYPE_SCRIPT) {
3017 if (nsContentUtils::IsJavascriptMIMEType(
3018 NS_ConvertUTF8toUTF16(contentType))) {
3019 return NS_OK;
3020 }
3021 ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType,
3022 Report::Error);
3023 return NS_ERROR_CORRUPTED_CONTENT;
3024 }
3025
3026 auto policyType = aLoadInfo->GetExternalContentPolicyType();
3027 if (policyType == ExtContentPolicy::TYPE_DOCUMENT ||
3028 policyType == ExtContentPolicy::TYPE_SUBDOCUMENT ||
3029 policyType == ExtContentPolicy::TYPE_OBJECT) {
3030 // If the header XCTO nosniff is set for any browsing context, then
3031 // we set the skipContentSniffing flag on the Loadinfo. Within
3032 // GetMIMETypeFromContent we then bail early and do not do any sniffing.
3033 aLoadInfo->SetSkipContentSniffing(true);
3034 return NS_OK;
3035 }
3036
3037 return NS_OK;
3038}
3039
3040nsresult EnsureMIMEOfJSONModule(HttpBaseChannel* aChannel, nsIURI* aURI,
3041 nsHttpResponseHead* aResponseHead,
3042 nsILoadInfo* aLoadInfo) {
3043 if (!aURI || !aResponseHead || !aLoadInfo) {
3044 // if there is no uri, no response head or no loadInfo, then there is
3045 // nothing to do
3046 return NS_OK;
3047 }
3048
3049 if (aLoadInfo->GetExternalContentPolicyType() !=
3050 ExtContentPolicy::TYPE_JSON) {
3051 // if this is not a JSON load, then there is nothing to do
3052 return NS_OK;
3053 }
3054
3055 nsAutoCString contentType;
3056 aResponseHead->ContentType(contentType);
3057 NS_ConvertUTF8toUTF16 typeString(contentType);
3058
3059 if (nsContentUtils::IsJsonMimeType(typeString)) {
3060 return NS_OK;
3061 }
3062
3063 ReportMimeTypeMismatch(aChannel, "BlockJsonModuleWithWrongMimeType", aURI,
3064 contentType, Report::Error);
3065 return NS_ERROR_CORRUPTED_CONTENT;
3066}
3067
3068// Ensure that a load of type script has correct MIME type
3069nsresult EnsureMIMEOfScript(HttpBaseChannel* aChannel, nsIURI* aURI,
3070 nsHttpResponseHead* aResponseHead,
3071 nsILoadInfo* aLoadInfo) {
3072 if (!aURI || !aResponseHead || !aLoadInfo) {
3073 // if there is no uri, no response head or no loadInfo, then there is
3074 // nothing to do
3075 return NS_OK;
3076 }
3077
3078 if (aLoadInfo->GetExternalContentPolicyType() !=
3079 ExtContentPolicy::TYPE_SCRIPT) {
3080 // if this is not a script load, then there is nothing to do
3081 return NS_OK;
3082 }
3083
3084 nsAutoCString contentType;
3085 aResponseHead->ContentType(contentType);
3086 NS_ConvertUTF8toUTF16 typeString(contentType);
3087
3088 if (nsContentUtils::IsJavascriptMIMEType(typeString)) {
3089 // script load has type script
3090 glean::http::script_block_incorrect_mime
3091 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eJavascript)
3092 .Add();
3093 return NS_OK;
3094 }
3095
3096 const auto internalPolicyType = aLoadInfo->InternalContentPolicyType();
3097 if (internalPolicyType ==
3098 nsIContentPolicy::TYPE_INTERNAL_WORKER_STATIC_MODULE &&
3099 nsContentUtils::IsJsonMimeType(typeString)) {
3100 // script and json are both allowed
3101 glean::http::script_block_incorrect_mime
3102 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextJson)
3103 .Add();
3104 return NS_OK;
3105 }
3106
3107 switch (aLoadInfo->InternalContentPolicyType()) {
3108 case nsIContentPolicy::TYPE_SCRIPT:
3109 case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
3110 case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
3111 case nsIContentPolicy::TYPE_INTERNAL_MODULE:
3112 case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD:
3113 case nsIContentPolicy::TYPE_INTERNAL_CHROMEUTILS_COMPILED_SCRIPT:
3114 case nsIContentPolicy::TYPE_INTERNAL_FRAME_MESSAGEMANAGER_SCRIPT:
3115 glean::http::script_block_incorrect_mime
3116 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eScriptLoad)
3117 .Add();
3118 break;
3119 case nsIContentPolicy::TYPE_INTERNAL_WORKER:
3120 case nsIContentPolicy::TYPE_INTERNAL_WORKER_STATIC_MODULE:
3121 case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
3122 glean::http::script_block_incorrect_mime
3123 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eWorkerLoad)
3124 .Add();
3125 break;
3126 case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
3127 glean::http::script_block_incorrect_mime
3128 .EnumGet(
3129 glean::http::ScriptBlockIncorrectMimeLabel::eServiceworkerLoad)
3130 .Add();
3131 break;
3132 case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
3133 glean::http::script_block_incorrect_mime
3134 .EnumGet(
3135 glean::http::ScriptBlockIncorrectMimeLabel::eImportscriptLoad)
3136 .Add();
3137 break;
3138 case nsIContentPolicy::TYPE_INTERNAL_AUDIOWORKLET:
3139 case nsIContentPolicy::TYPE_INTERNAL_PAINTWORKLET:
3140 glean::http::script_block_incorrect_mime
3141 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eWorkletLoad)
3142 .Add();
3143 break;
3144 default:
3145 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"
, 3145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected script type" ")"); do
{ MOZ_CrashSequence(__null, 3145); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3146 break;
3147 }
3148
3149 if (aLoadInfo->GetLoadingPrincipal()->IsSameOrigin(aURI)) {
3150 // same origin
3151 glean::http::script_block_incorrect_mime
3152 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eSameOrigin)
3153 .Add();
3154 } else {
3155 bool cors = false;
3156 nsAutoCString corsOrigin;
3157 nsresult rv = aResponseHead->GetHeader(
3158 nsHttp::ResolveAtom("Access-Control-Allow-Origin"_ns), corsOrigin);
3159 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3160 if (corsOrigin.Equals("*")) {
3161 cors = true;
3162 } else {
3163 nsCOMPtr<nsIURI> corsOriginURI;
3164 rv = NS_NewURI(getter_AddRefs(corsOriginURI), corsOrigin);
3165 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3166 if (aLoadInfo->GetLoadingPrincipal()->IsSameOrigin(corsOriginURI)) {
3167 cors = true;
3168 }
3169 }
3170 }
3171 }
3172 if (cors) {
3173 // cors origin
3174 glean::http::script_block_incorrect_mime
3175 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eCorsOrigin)
3176 .Add();
3177 } else {
3178 // cross origin
3179 glean::http::script_block_incorrect_mime
3180 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eCrossOrigin)
3181 .Add();
3182 }
3183 }
3184
3185 bool block = false;
3186 if (StringBeginsWith(contentType, "image/"_ns)) {
3187 // script load has type image
3188 glean::http::script_block_incorrect_mime
3189 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eImage)
3190 .Add();
3191 block = true;
3192 } else if (StringBeginsWith(contentType, "audio/"_ns)) {
3193 // script load has type audio
3194 glean::http::script_block_incorrect_mime
3195 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eAudio)
3196 .Add();
3197 block = true;
3198 } else if (StringBeginsWith(contentType, "video/"_ns)) {
3199 // script load has type video
3200 glean::http::script_block_incorrect_mime
3201 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eVideo)
3202 .Add();
3203 block = true;
3204 } else if (StringBeginsWith(contentType, "text/csv"_ns)) {
3205 // script load has type text/csv
3206 glean::http::script_block_incorrect_mime
3207 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextCsv)
3208 .Add();
3209 block = true;
3210 }
3211
3212 if (block) {
3213 ReportMimeTypeMismatch(aChannel, "BlockScriptWithWrongMimeType2", aURI,
3214 contentType, Report::Error);
3215 return NS_ERROR_CORRUPTED_CONTENT;
3216 }
3217
3218 if (StringBeginsWith(contentType, "text/plain"_ns)) {
3219 // script load has type text/plain
3220 glean::http::script_block_incorrect_mime
3221 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextPlain)
3222 .Add();
3223 } else if (StringBeginsWith(contentType, "text/xml"_ns)) {
3224 // script load has type text/xml
3225 glean::http::script_block_incorrect_mime
3226 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextXml)
3227 .Add();
3228 } else if (StringBeginsWith(contentType, "application/octet-stream"_ns)) {
3229 // script load has type application/octet-stream
3230 glean::http::script_block_incorrect_mime
3231 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eAppOctetStream)
3232 .Add();
3233 } else if (StringBeginsWith(contentType, "application/xml"_ns)) {
3234 // script load has type application/xml
3235 glean::http::script_block_incorrect_mime
3236 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eAppXml)
3237 .Add();
3238 } else if (StringBeginsWith(contentType, "application/json"_ns)) {
3239 // script load has type application/json
3240 glean::http::script_block_incorrect_mime
3241 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eAppJson)
3242 .Add();
3243 } else if (StringBeginsWith(contentType, "text/json"_ns)) {
3244 // script load has type text/json
3245 glean::http::script_block_incorrect_mime
3246 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextJson)
3247 .Add();
3248 } else if (StringBeginsWith(contentType, "text/html"_ns)) {
3249 // script load has type text/html
3250 glean::http::script_block_incorrect_mime
3251 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eTextHtml)
3252 .Add();
3253 } else if (contentType.IsEmpty()) {
3254 // script load has no type
3255 glean::http::script_block_incorrect_mime
3256 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eEmpty)
3257 .Add();
3258 } else {
3259 // script load has unknown type
3260 glean::http::script_block_incorrect_mime
3261 .EnumGet(glean::http::ScriptBlockIncorrectMimeLabel::eUnknown)
3262 .Add();
3263 }
3264
3265 nsContentPolicyType internalType = aLoadInfo->InternalContentPolicyType();
3266
3267 // We restrict importScripts() in worker code to JavaScript MIME types.
3268 if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS) {
3269 ReportMimeTypeMismatch(aChannel, "BlockImportScriptsWithWrongMimeType",
3270 aURI, contentType, Report::Error);
3271 return NS_ERROR_CORRUPTED_CONTENT;
3272 }
3273
3274 if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER_STATIC_MODULE) {
3275#ifdef NIGHTLY_BUILD1
3276 if (StaticPrefs::javascript_options_experimental_wasm_esm_integration()) {
3277 if (nsContentUtils::HasWasmMimeTypeEssence(typeString)) {
3278 return NS_OK;
3279 }
3280 }
3281#endif
3282 ReportMimeTypeMismatch(aChannel, "BlockModuleWithWrongMimeType", aURI,
3283 contentType, Report::Error);
3284 return NS_ERROR_CORRUPTED_CONTENT;
3285 }
3286
3287 if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
3288 internalType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER) {
3289 // Do not block the load if the feature is not enabled.
3290 if (!StaticPrefs::security_block_Worker_with_wrong_mime()) {
3291 return NS_OK;
3292 }
3293
3294#ifdef NIGHTLY_BUILD1
3295 if (StaticPrefs::javascript_options_experimental_wasm_esm_integration()) {
3296 if (nsContentUtils::HasWasmMimeTypeEssence(typeString)) {
3297 return NS_OK;
3298 }
3299 }
3300#endif
3301
3302 ReportMimeTypeMismatch(aChannel, "BlockWorkerWithWrongMimeType", aURI,
3303 contentType, Report::Error);
3304 return NS_ERROR_CORRUPTED_CONTENT;
3305 }
3306
3307 // ES6 modules require a strict MIME type check.
3308 if (internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE ||
3309 internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD) {
3310#ifdef NIGHTLY_BUILD1
3311 if (StaticPrefs::javascript_options_experimental_wasm_esm_integration()) {
3312 if (nsContentUtils::HasWasmMimeTypeEssence(typeString)) {
3313 return NS_OK;
3314 }
3315 }
3316#endif
3317
3318 ReportMimeTypeMismatch(aChannel, "BlockModuleWithWrongMimeType", aURI,
3319 contentType, Report::Error);
3320 return NS_ERROR_CORRUPTED_CONTENT;
3321 }
3322
3323 return NS_OK;
3324}
3325
3326// Warn when a load of type script uses a wrong MIME type and
3327// wasn't blocked by EnsureMIMEOfScript or ProcessXCTO.
3328void WarnWrongMIMEOfScript(HttpBaseChannel* aChannel, nsIURI* aURI,
3329 nsHttpResponseHead* aResponseHead,
3330 nsILoadInfo* aLoadInfo) {
3331 if (!aURI || !aResponseHead || !aLoadInfo) {
3332 // If there is no uri, no response head or no loadInfo, then there is
3333 // nothing to do.
3334 return;
3335 }
3336
3337 if (aLoadInfo->GetExternalContentPolicyType() !=
3338 ExtContentPolicy::TYPE_SCRIPT) {
3339 // If this is not a script load, then there is nothing to do.
3340 return;
3341 }
3342
3343 bool succeeded;
3344 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", 3344
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(aChannel->GetRequestSucceeded(&succeeded))"
")"); do { MOZ_CrashSequence(__null, 3344); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3345 if (!succeeded) {
3346 // Do not warn for failed loads: HTTP error pages are usually in HTML.
3347 return;
3348 }
3349
3350 nsAutoCString contentType;
3351 aResponseHead->ContentType(contentType);
3352 NS_ConvertUTF8toUTF16 typeString(contentType);
3353
3354 if (nsContentUtils::IsJavascriptMIMEType(typeString)) {
3355 return;
3356 }
3357
3358#ifdef NIGHTLY_BUILD1
3359 if (StaticPrefs::javascript_options_experimental_wasm_esm_integration()) {
3360 if (nsContentUtils::HasWasmMimeTypeEssence(typeString)) {
3361 return;
3362 }
3363 }
3364#endif
3365
3366 ReportMimeTypeMismatch(aChannel, "WarnScriptWithWrongMimeType", aURI,
3367 contentType, Report::Warning);
3368}
3369
3370nsresult HttpBaseChannel::ValidateMIMEType() {
3371 nsresult rv = EnsureMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo);
3372 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3373 return rv;
3374 }
3375
3376 rv = EnsureMIMEOfJSONModule(this, mURI, mResponseHead.get(), mLoadInfo);
3377 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3378 return rv;
3379 }
3380
3381 rv = ProcessXCTO(this, mURI, mResponseHead.get(), mLoadInfo);
3382 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3383 return rv;
3384 }
3385
3386 WarnWrongMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo);
3387 return NS_OK;
3388}
3389
3390bool HttpBaseChannel::ShouldFilterOpaqueResponse(
3391 OpaqueResponseFilterFetch aFilterType) const {
3392 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", 3392
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ShouldBlockOpaqueResponse()"
")"); do { MOZ_CrashSequence(__null, 3392); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3393
3394 if (!mLoadInfo || ConfiguredFilterFetchResponseBehaviour() != aFilterType) {
3395 return false;
3396 }
3397
3398 // We should filter a response in the parent if it is opaque and is the result
3399 // of a fetch() function from the Fetch specification.
3400 return mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_FETCH;
3401}
3402
3403bool HttpBaseChannel::ShouldBlockOpaqueResponse() const {
3404 if (!mURI || !mResponseHead || !mLoadInfo) {
3405 // if there is no uri, no response head or no loadInfo, then there is
3406 // nothing to do
3407 LOGORB("No block: no mURI, mResponseHead, or mLoadInfo");
3408 return false;
3409 }
3410
3411 nsCOMPtr<nsIPrincipal> principal = mLoadInfo->GetLoadingPrincipal();
3412 if (!principal || principal->IsSystemPrincipal()) {
3413 // If it's a top-level load or a system principal, then there is nothing to
3414 // do.
3415 LOGORB("No block: top-level load or system principal");
3416 return false;
3417 }
3418
3419 // Check if the response is a opaque response, which means requestMode should
3420 // be RequestMode::No_cors and responseType should be ResponseType::Opaque.
3421 nsContentPolicyType contentPolicy = mLoadInfo->InternalContentPolicyType();
3422
3423 // Skip the RequestMode would be RequestMode::Navigate
3424 if (contentPolicy == nsIContentPolicy::TYPE_DOCUMENT ||
3425 contentPolicy == nsIContentPolicy::TYPE_SUBDOCUMENT ||
3426 contentPolicy == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
3427 contentPolicy == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
3428 // Skip the RequestMode would be RequestMode::Same_origin
3429 contentPolicy == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
3430 contentPolicy == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER) {
3431 return false;
3432 }
3433
3434 uint32_t securityMode = mLoadInfo->GetSecurityMode();
3435 // Skip when RequestMode would not be RequestMode::no_cors
3436 if (securityMode !=
3437 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT &&
3438 securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL) {
3439 LOGORB("No block: not no_cors requests");
3440 return false;
3441 }
3442
3443 // Only continue when ResponseType would be ResponseType::Opaque
3444 if (mLoadInfo->GetTainting() != mozilla::LoadTainting::Opaque) {
3445 LOGORB("No block: not opaque response");
3446 return false;
3447 }
3448
3449 auto extContentPolicyType = mLoadInfo->GetExternalContentPolicyType();
3450 if (extContentPolicyType == ExtContentPolicy::TYPE_OBJECT ||
3451 extContentPolicyType == ExtContentPolicy::TYPE_WEBSOCKET ||
3452 extContentPolicyType == ExtContentPolicy::TYPE_SAVEAS_DOWNLOAD) {
3453 LOGORB("No block: object || websocket request || save as download");
3454 return false;
3455 }
3456
3457 // Exclude no_cors System XHR
3458 if (extContentPolicyType == ExtContentPolicy::TYPE_XMLHTTPREQUEST) {
3459 if (securityMode ==
3460 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT) {
3461 LOGORB("No block: System XHR");
3462 return false;
3463 }
3464 }
3465
3466 // Exclude no_cors web-identity
3467 if (extContentPolicyType == ExtContentPolicy::TYPE_WEB_IDENTITY) {
3468 if (securityMode ==
3469 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT) {
3470 printf("Allowing ORB for web-identity\n");
3471 LOGORB("No block: System web-identity");
3472 return false;
3473 }
3474 }
3475
3476 uint32_t httpsOnlyStatus = mLoadInfo->GetHttpsOnlyStatus();
3477 if (httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_BYPASS_ORB) {
3478 LOGORB("No block: HTTPS_ONLY_BYPASS_ORB");
3479 return false;
3480 }
3481
3482 return true;
3483}
3484
3485OpaqueResponse HttpBaseChannel::BlockOrFilterOpaqueResponse(
3486 OpaqueResponseBlocker* aORB, const nsAString& aReason,
3487 const OpaqueResponseBlockedTelemetryReason aTelemetryReason,
3488 const char* aFormat, ...) {
3489 NimbusFeatures::RecordExposureEvent("opaqueResponseBlocking"_ns, true);
3490
3491 const bool shouldFilter =
3492 ShouldFilterOpaqueResponse(OpaqueResponseFilterFetch::BlockedByORB);
3493
3494 if (MOZ_UNLIKELY(MOZ_LOG_TEST(GetORBLog(), LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(GetORBLog(), LogLevel::Debug)), 0))), 0))
) {
3495 va_list ap;
3496 va_start(ap, aFormat)__builtin_va_start(ap, aFormat);
3497 nsVprintfCString logString(aFormat, ap);
3498 va_end(ap)__builtin_va_end(ap);
3499
3500 LOGORB("%s: %s", shouldFilter ? "Filtered" : "Blocked", logString.get());
3501 }
3502
3503 if (shouldFilter) {
3504 glean::orb::block_initiator
3505 .EnumGet(glean::orb::BlockInitiatorLabel::eFilteredFetch)
3506 .Add();
3507 // The existence of `mORB` depends on `BlockOrFilterOpaqueResponse` being
3508 // called before or after sniffing has completed.
3509 // Another requirement is that `OpaqueResponseFilter` must come after
3510 // `OpaqueResponseBlocker`, which is why in the case of having an
3511 // `OpaqueResponseBlocker` we let it handle creating an
3512 // `OpaqueResponseFilter`.
3513 if (aORB) {
3514 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", 3514
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mORB || aORB == mORB"
")"); do { MOZ_CrashSequence(__null, 3514); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3515 aORB->FilterResponse();
3516 } else {
3517 mListener = new OpaqueResponseFilter(mListener);
3518 }
3519 return OpaqueResponse::Allow;
3520 }
3521
3522 LogORBError(aReason, aTelemetryReason);
3523 return OpaqueResponse::Block;
3524}
3525
3526dom::NoCorsMediaRequestState HttpBaseChannel::NoCorsMediaRequestState() {
3527 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", 3527
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3528
3529 if (!mLoadInfo->GetIsMediaRequest()) {
3530 return dom::NoCorsMediaRequestState::NotAvailable;
3531 }
3532
3533 RefPtr<dom::WindowGlobalParent> wgp =
3534 dom::WindowGlobalParent::GetByInnerWindowId(
3535 mLoadInfo->GetInnerWindowID());
3536 if (!wgp || wgp->IsDiscarded()) {
3537 return dom::NoCorsMediaRequestState::NotAvailable;
3538 }
3539
3540 return wgp->NoCorsMediaRequestState(mURI);
3541}
3542
3543void HttpBaseChannel::RecordSubsequentNoCorsRequestState() {
3544 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", 3544
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3544); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3545 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"
, 3545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetIsMediaRequest()"
")"); do { MOZ_CrashSequence(__null, 3545); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3546
3547 RefPtr<dom::WindowGlobalParent> wgp =
3548 dom::WindowGlobalParent::GetByInnerWindowId(
3549 mLoadInfo->GetInnerWindowID());
3550 if (!wgp || wgp->IsDiscarded()) {
3551 return;
3552 }
3553
3554 wgp->RecordSubsequentNoCorsRequestState(mURI);
3555}
3556
3557// The specification for ORB is currently being written:
3558// https://whatpr.org/fetch/1442.html#orb-algorithm
3559// The `opaque-response-safelist check` is implemented in:
3560// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff`
3561// * `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
3562// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff`
3563// * `OpaqueResponseBlocker::ValidateJavaScript`
3564OpaqueResponse
3565HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff() {
3566 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", 3566
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3566); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3567
3568 // https://whatpr.org/fetch/1442.html#http-fetch, step 6.4
3569 if (!ShouldBlockOpaqueResponse()) {
3570 return OpaqueResponse::Allow;
3571 }
3572
3573 // Regardless of if ORB is enabled or not, we check if we should filter the
3574 // response in the parent. This way data won't reach a content process that
3575 // will create a filtered `Response` object. This is enabled when
3576 // 'browser.opaqueResponseBlocking.filterFetchResponse' is
3577 // `OpaqueResponseFilterFetch::All`.
3578 // See https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
3579 if (ShouldFilterOpaqueResponse(OpaqueResponseFilterFetch::All)) {
3580 mListener = new OpaqueResponseFilter(mListener);
3581
3582 // If we're filtering a response in the parent, there will be no data to
3583 // determine if it should be blocked or not so the only option we have is to
3584 // allow it.
3585 return OpaqueResponse::Allow;
3586 }
3587
3588 if (!mCachedOpaqueResponseBlockingPref) {
3589 return OpaqueResponse::Allow;
3590 }
3591
3592 // If ORB is enabled, we check if we should filter the response in the parent.
3593 // This way data won't reach a content process that will create a filtered
3594 // `Response` object. We allow ORB to determine if the response should be
3595 // blocked or filtered, but regardless no data should reach the content
3596 // process. This is enabled when
3597 // 'browser.opaqueResponseBlocking.filterFetchResponse' is
3598 // `OpaqueResponseFilterFetch::AllowedByORB`.
3599 // See https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
3600 if (ShouldFilterOpaqueResponse(OpaqueResponseFilterFetch::AllowedByORB)) {
3601 mListener = new OpaqueResponseFilter(mListener);
3602 }
3603
3604 glean::opaque_response_blocking::cross_origin_opaque_response_count.Add(1);
3605
3606 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)
;
3607
3608 // https://whatpr.org/fetch/1442.html#orb-algorithm
3609 // Step 1
3610 nsAutoCString contentType;
3611 mResponseHead->ContentType(contentType);
3612
3613 // Step 2
3614 nsAutoCString contentTypeOptionsHeader;
3615 bool nosniff =
3616 mResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader) &&
3617 contentTypeOptionsHeader.EqualsIgnoreCase("nosniff");
3618
3619 // Step 3
3620 switch (GetOpaqueResponseBlockedReason(contentType, mResponseHead->Status(),
3621 nosniff)) {
3622 case OpaqueResponseBlockedReason::ALLOWED_SAFE_LISTED:
3623 // Step 3.1
3624 return OpaqueResponse::Allow;
3625 case OpaqueResponseBlockedReason::ALLOWED_SAFE_LISTED_SPEC_BREAKING:
3626 LOGORB("Allowed %s in a spec breaking way", contentType.get());
3627 return OpaqueResponse::Allow;
3628 case OpaqueResponseBlockedReason::BLOCKED_BLOCKLISTED_NEVER_SNIFFED:
3629 return BlockOrFilterOpaqueResponse(
3630 mORB, u"mimeType is an opaque-blocklisted-never-sniffed MIME type"_ns,
3631 OpaqueResponseBlockedTelemetryReason::eMimeNeverSniffed,
3632 "BLOCKED_BLOCKLISTED_NEVER_SNIFFED");
3633 case OpaqueResponseBlockedReason::BLOCKED_206_AND_BLOCKLISTED:
3634 // Step 3.3
3635 return BlockOrFilterOpaqueResponse(
3636 mORB,
3637 u"response's status is 206 and mimeType is an opaque-blocklisted MIME type"_ns,
3638 OpaqueResponseBlockedTelemetryReason::eResp206Blclisted,
3639 "BLOCKED_206_AND_BLOCKEDLISTED");
3640 case OpaqueResponseBlockedReason::
3641 BLOCKED_NOSNIFF_AND_EITHER_BLOCKLISTED_OR_TEXTPLAIN:
3642 // Step 3.4
3643 return BlockOrFilterOpaqueResponse(
3644 mORB,
3645 u"nosniff is true and mimeType is an opaque-blocklisted MIME type or its essence is 'text/plain'"_ns,
3646 OpaqueResponseBlockedTelemetryReason::eNosniffBlcOrTextp,
3647 "BLOCKED_NOSNIFF_AND_EITHER_BLOCKLISTED_OR_TEXTPLAIN");
3648 default:
3649 break;
3650 }
3651
3652 // Step 4
3653 // If it's a media subsequent request, we assume that it will only be made
3654 // after a successful initial request.
3655 if (NoCorsMediaRequestState() == dom::NoCorsMediaRequestState::Subsequent) {
3656 return OpaqueResponse::Allow;
3657 }
3658
3659 // Step 5
3660 if (mResponseHead->Status() == 206 &&
3661 !IsFirstPartialResponse(*mResponseHead)) {
3662 return BlockOrFilterOpaqueResponse(
3663 mORB, u"response status is 206 and not first partial response"_ns,
3664 OpaqueResponseBlockedTelemetryReason::eResp206Blclisted,
3665 "Is not a valid partial response given 0");
3666 }
3667
3668 // Setup for steps 6, 7, 8 and 10.
3669 // Steps 6 and 7 are handled by the sniffer framework.
3670 // Steps 8 and 10 by are handled by
3671 // `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
3672 if (mLoadFlags & nsIChannel::LOAD_CALL_CONTENT_SNIFFERS) {
3673 mSnifferCategoryType = SnifferCategoryType::All;
3674 } else {
3675 mSnifferCategoryType = SnifferCategoryType::OpaqueResponseBlocking;
3676 }
3677
3678 mLoadFlags |= (nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
3679 nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE);
3680
3681 // Install an input stream listener that performs ORB checks that depend on
3682 // inspecting the incoming data. It is crucial that `OnStartRequest` is called
3683 // on this listener either after sniffing is completed or that we skip
3684 // sniffing, otherwise `OpaqueResponseBlocker` will allow responses that it
3685 // shouldn't.
3686 mORB = new OpaqueResponseBlocker(mListener, this, contentType, nosniff);
3687 mListener = mORB;
3688
3689 nsAutoCString contentEncoding;
3690 nsresult rv =
3691 mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
3692
3693 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !contentEncoding.IsEmpty()) {
3694 return OpaqueResponse::SniffCompressed;
3695 }
3696 mLoadFlags |= (nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
3697 nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE);
3698 return OpaqueResponse::Sniff;
3699}
3700
3701// The specification for ORB is currently being written:
3702// https://whatpr.org/fetch/1442.html#orb-algorithm
3703// The `opaque-response-safelist check` is implemented in:
3704// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff`
3705// * `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
3706// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff`
3707// * `OpaqueResponseBlocker::ValidateJavaScript`
3708OpaqueResponse HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff(
3709 const nsACString& aContentType, bool aNoSniff) {
3710 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)
;
3711
3712 // https://whatpr.org/fetch/1442.html#orb-algorithm
3713 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", 3713
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 3713); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3714 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"
, 3714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedOpaqueResponseBlockingPref"
")"); do { MOZ_CrashSequence(__null, 3714); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3715
3716 // Step 9
3717 if (NoCorsMediaRequestState() != dom::NoCorsMediaRequestState::NotAvailable) {
3718 return BlockOrFilterOpaqueResponse(
3719 mORB, u"after sniff: media request"_ns,
3720 OpaqueResponseBlockedTelemetryReason::eAfterSniffMedia,
3721 "media request");
3722 }
3723
3724 // Step 11
3725 if (aNoSniff) {
3726 return BlockOrFilterOpaqueResponse(
3727 mORB, u"after sniff: nosniff is true"_ns,
3728 OpaqueResponseBlockedTelemetryReason::eAfterSniffNosniff, "nosniff");
3729 }
3730
3731 // Step 12
3732 if (mResponseHead &&
3733 (mResponseHead->Status() < 200 || mResponseHead->Status() > 299)) {
3734 return BlockOrFilterOpaqueResponse(
3735 mORB, u"after sniff: status code is not in allowed range"_ns,
3736 OpaqueResponseBlockedTelemetryReason::eAfterSniffStaCode,
3737 "status code (%d) is not allowed", mResponseHead->Status());
3738 }
3739
3740 // Step 13
3741 if (!mResponseHead || aContentType.IsEmpty()) {
3742 LOGORB("Allowed: mimeType is failure");
3743 return OpaqueResponse::Allow;
3744 }
3745
3746 // Step 14
3747 if (StringBeginsWith(aContentType, "image/"_ns) ||
3748 StringBeginsWith(aContentType, "video/"_ns) ||
3749 StringBeginsWith(aContentType, "audio/"_ns)) {
3750 return BlockOrFilterOpaqueResponse(
3751 mORB,
3752 u"after sniff: content-type declares image/video/audio, but sniffing fails"_ns,
3753 OpaqueResponseBlockedTelemetryReason::eAfterSniffCtFail,
3754 "ContentType is image/video/audio");
3755 }
3756
3757 return OpaqueResponse::Sniff;
3758}
3759
3760bool HttpBaseChannel::NeedOpaqueResponseAllowedCheckAfterSniff() const {
3761 RefPtr<OpaqueResponseBlocker> orb(mORB);
3762 return orb ? orb->IsSniffing() : false;
3763}
3764
3765void HttpBaseChannel::BlockOpaqueResponseAfterSniff(
3766 const nsAString& aReason,
3767 const OpaqueResponseBlockedTelemetryReason aTelemetryReason) {
3768 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"
, 3768); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mORB"
")"); do { MOZ_CrashSequence(__null, 3768); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3769 LogORBError(aReason, aTelemetryReason);
3770 RefPtr<OpaqueResponseBlocker> orb(mORB);
3771 orb->BlockResponse(this, NS_ERROR_DOM_NETWORK_ERR);
3772}
3773
3774void HttpBaseChannel::AllowOpaqueResponseAfterSniff() {
3775 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"
, 3775); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mORB"
")"); do { MOZ_CrashSequence(__null, 3775); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3776 RefPtr<OpaqueResponseBlocker> orb(mORB);
3777 orb->AllowResponse();
3778}
3779
3780void HttpBaseChannel::SetChannelBlockedByOpaqueResponse() {
3781 mChannelBlockedByOpaqueResponse = true;
3782
3783 RefPtr<dom::BrowsingContext> browsingContext =
3784 dom::BrowsingContext::GetCurrentTopByBrowserId(mBrowserId);
3785 if (!browsingContext) {
3786 return;
3787 }
3788
3789 dom::WindowContext* windowContext = browsingContext->GetTopWindowContext();
3790 if (windowContext) {
3791 windowContext->Canonical()->SetShouldReportHasBlockedOpaqueResponse(
3792 mLoadInfo->InternalContentPolicyType());
3793 }
3794}
3795
3796nsresult HttpBaseChannel::SetCookieHeaders(
3797 const nsTArray<nsCString>& aCookieHeaders) {
3798 if (mLoadFlags & LOAD_ANONYMOUS) return NS_OK;
3799
3800 // The loadGroup of the channel in the parent process could be null in the
3801 // XPCShell content process test, see test_cookiejars_wrap.js. In this case,
3802 // we cannot explicitly set the loadGroup for the parent channel because it's
3803 // created from the content process. To workaround this, we add a testing pref
3804 // to skip this check.
3805 if (!StaticPrefs::
3806 network_cookie_skip_browsing_context_check_in_parent_for_testing() &&
3807 IsBrowsingContextDiscarded()) {
3808 return NS_OK;
3809 }
3810
3811 // empty header isn't an error
3812 if (aCookieHeaders.IsEmpty()) {
3813 return NS_OK;
3814 }
3815
3816 nsICookieService* cs = gHttpHandler->GetCookieService();
3817 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"
, 3817); return NS_ERROR_FAILURE; } } while (false)
;
3818
3819 for (const nsCString& cookieHeader : aCookieHeaders) {
3820 nsresult rv = cs->SetCookieStringFromHttp(mURI, cookieHeader, this);
3821 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"
, 3821); return rv; } } while (false)
;
3822 }
3823
3824 return NS_OK;
3825}
3826
3827NS_IMETHODIMPnsresult
3828HttpBaseChannel::GetThirdPartyFlags(uint32_t* aFlags) {
3829 *aFlags = LoadThirdPartyFlags();
3830 return NS_OK;
3831}
3832
3833NS_IMETHODIMPnsresult
3834HttpBaseChannel::SetThirdPartyFlags(uint32_t aFlags) {
3835 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3835); 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"
, 3835, 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"
, 3835); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3835); 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"
, 3835); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
3836
3837 StoreThirdPartyFlags(aFlags);
3838 return NS_OK;
3839}
3840
3841NS_IMETHODIMPnsresult
3842HttpBaseChannel::GetForceAllowThirdPartyCookie(bool* aForce) {
3843 *aForce = !!(LoadThirdPartyFlags() &
3844 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
3845 return NS_OK;
3846}
3847
3848NS_IMETHODIMPnsresult
3849HttpBaseChannel::SetForceAllowThirdPartyCookie(bool aForce) {
3850 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3850); 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"
, 3850, 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"
, 3850); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 3850); 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"
, 3850); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
3851
3852 if (aForce) {
3853 StoreThirdPartyFlags(LoadThirdPartyFlags() |
3854 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
3855 } else {
3856 StoreThirdPartyFlags(LoadThirdPartyFlags() &
3857 ~nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
3858 }
3859
3860 return NS_OK;
3861}
3862
3863NS_IMETHODIMPnsresult
3864HttpBaseChannel::GetCanceled(bool* aCanceled) {
3865 *aCanceled = mCanceled;
3866 return NS_OK;
3867}
3868
3869NS_IMETHODIMPnsresult
3870HttpBaseChannel::GetChannelIsForDownload(bool* aChannelIsForDownload) {
3871 *aChannelIsForDownload = LoadChannelIsForDownload();
3872 return NS_OK;
3873}
3874
3875NS_IMETHODIMPnsresult
3876HttpBaseChannel::SetChannelIsForDownload(bool aChannelIsForDownload) {
3877 StoreChannelIsForDownload(aChannelIsForDownload);
3878 return NS_OK;
3879}
3880
3881NS_IMETHODIMPnsresult
3882HttpBaseChannel::SetCacheKeysRedirectChain(nsTArray<nsCString>* cacheKeys) {
3883 auto RedirectedCachekeys = mRedirectedCachekeys.Lock();
3884 auto& ref = RedirectedCachekeys.ref();
3885 ref = WrapUnique(cacheKeys);
3886 return NS_OK;
3887}
3888
3889NS_IMETHODIMPnsresult
3890HttpBaseChannel::GetLocalAddress(nsACString& addr) {
3891 if (mSelfAddr.raw.family == PR_AF_UNSPEC0) return NS_ERROR_NOT_AVAILABLE;
3892
3893 mSelfAddr.ToString(addr);
3894
3895 return NS_OK;
3896}
3897
3898NS_IMETHODIMPnsresult
3899HttpBaseChannel::TakeAllSecurityMessages(
3900 nsCOMArray<nsISecurityConsoleMessage>& aMessages) {
3901 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", 3901
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 3901); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3902
3903 aMessages.Clear();
3904 for (const auto& pair : mSecurityConsoleMessages) {
3905 nsresult rv;
3906 nsCOMPtr<nsISecurityConsoleMessage> message =
3907 do_CreateInstance(NS_SECURITY_CONSOLE_MESSAGE_CONTRACTID"@mozilla.org/securityconsole/message;1", &rv);
3908 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"
, 3908); return rv; } } while (false)
;
3909
3910 message->SetTag(pair.first);
3911 message->SetCategory(pair.second);
3912 aMessages.AppendElement(message);
3913 }
3914
3915 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"
, 3915); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSecurityConsoleMessages.Length() == aMessages.Length()"
")"); do { MOZ_CrashSequence(__null, 3915); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3916 mSecurityConsoleMessages.Clear();
3917
3918 return NS_OK;
3919}
3920
3921/* Please use this method with care. This can cause the message
3922 * queue to grow large and cause the channel to take up a lot
3923 * of memory. Use only static string messages and do not add
3924 * server side data to the queue, as that can be large.
3925 * Add only a limited number of messages to the queue to keep
3926 * the channel size down and do so only in rare erroneous situations.
3927 * More information can be found here:
3928 * https://bugzilla.mozilla.org/show_bug.cgi?id=846918
3929 */
3930nsresult HttpBaseChannel::AddSecurityMessage(
3931 const nsAString& aMessageTag, const nsAString& aMessageCategory) {
3932 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", 3932
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 3932); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3933
3934 nsresult rv;
3935
3936 // nsSecurityConsoleMessage is not thread-safe refcounted.
3937 // Delay the object construction until requested.
3938 // See TakeAllSecurityMessages()
3939 std::pair<nsString, nsString> pair(aMessageTag, aMessageCategory);
3940 mSecurityConsoleMessages.AppendElement(std::move(pair));
3941
3942 nsCOMPtr<nsIConsoleService> console(
3943 do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1"));
3944 if (!console) {
3945 return NS_ERROR_FAILURE;
3946 }
3947
3948 nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
3949
3950 auto innerWindowID = loadInfo->GetInnerWindowID();
3951
3952 nsAutoString errorText;
3953 rv = nsContentUtils::GetLocalizedString(
3954 PropertiesFile::SECURITY_PROPERTIES,
3955 NS_ConvertUTF16toUTF8(aMessageTag).get(), errorText);
3956 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"
, 3956); return rv; } } while (false)
;
3957
3958 nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1"));
3959 error->InitWithSourceURI(errorText, mURI, 0, 0, nsIScriptError::warningFlag,
3960 NS_ConvertUTF16toUTF8(aMessageCategory),
3961 innerWindowID);
3962
3963 console->LogMessage(error);
3964
3965 return NS_OK;
3966}
3967
3968NS_IMETHODIMPnsresult
3969HttpBaseChannel::GetLocalPort(int32_t* port) {
3970 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", 3970
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3971
3972 if (mSelfAddr.raw.family == PR_AF_INET2) {
3973 *port = (int32_t)ntohs(mSelfAddr.inet.port)__bswap_16 (mSelfAddr.inet.port);
3974 } else if (mSelfAddr.raw.family == PR_AF_INET610) {
3975 *port = (int32_t)ntohs(mSelfAddr.inet6.port)__bswap_16 (mSelfAddr.inet6.port);
3976 } else {
3977 return NS_ERROR_NOT_AVAILABLE;
3978 }
3979
3980 return NS_OK;
3981}
3982
3983NS_IMETHODIMPnsresult
3984HttpBaseChannel::GetRemoteAddress(nsACString& addr) {
3985 if (mPeerAddr.raw.family == PR_AF_UNSPEC0) return NS_ERROR_NOT_AVAILABLE;
3986
3987 mPeerAddr.ToString(addr);
3988
3989 return NS_OK;
3990}
3991
3992NS_IMETHODIMPnsresult
3993HttpBaseChannel::GetRemotePort(int32_t* port) {
3994 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", 3994
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3995
3996 if (mPeerAddr.raw.family == PR_AF_INET2) {
3997 *port = (int32_t)ntohs(mPeerAddr.inet.port)__bswap_16 (mPeerAddr.inet.port);
3998 } else if (mPeerAddr.raw.family == PR_AF_INET610) {
3999 *port = (int32_t)ntohs(mPeerAddr.inet6.port)__bswap_16 (mPeerAddr.inet6.port);
4000 } else {
4001 return NS_ERROR_NOT_AVAILABLE;
4002 }
4003
4004 return NS_OK;
4005}
4006
4007NS_IMETHODIMPnsresult
4008HttpBaseChannel::HTTPUpgrade(const nsACString& aProtocolName,
4009 nsIHttpUpgradeListener* aListener) {
4010 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"
, 4010); return NS_ERROR_INVALID_ARG; } } while (false)
;
4011 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", 4011
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4012
4013 // The protocol name is emitted verbatim into the Upgrade request header, so
4014 // reject anything that could inject additional headers or requests (e.g. an
4015 // embedded CRLF from a compromised child process).
4016 if (!nsHttp::IsReasonableHeaderValue(aProtocolName)) {
4017 return NS_ERROR_ILLEGAL_VALUE;
4018 }
4019
4020 mUpgradeProtocol = aProtocolName;
4021 mUpgradeProtocolCallback = aListener;
4022 return NS_OK;
4023}
4024
4025NS_IMETHODIMPnsresult
4026HttpBaseChannel::GetOnlyConnect(bool* aOnlyConnect) {
4027 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"
, 4027); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4028
4029 *aOnlyConnect = mCaps & NS_HTTP_CONNECT_ONLY(1 << 16);
4030 return NS_OK;
4031}
4032
4033NS_IMETHODIMPnsresult
4034HttpBaseChannel::SetConnectOnly(bool aTlsTunnel) {
4035 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4035); 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"
, 4035, 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"
, 4035); } } 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", 4035
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 4035); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
4036
4037 if (!mUpgradeProtocolCallback) {
4038 return NS_ERROR_FAILURE;
4039 }
4040
4041 mCaps |= NS_HTTP_CONNECT_ONLY(1 << 16);
4042 if (aTlsTunnel) {
4043 mCaps |= NS_HTTP_TLS_TUNNEL(1 << 29);
4044 }
4045 mProxyResolveFlags = nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
4046 nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL;
4047 return SetLoadFlags(nsIRequest::INHIBIT_CACHING | nsIChannel::LOAD_ANONYMOUS |
4048 nsIRequest::LOAD_BYPASS_CACHE |
4049 nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
4050}
4051
4052NS_IMETHODIMPnsresult
4053HttpBaseChannel::GetAllowSpdy(bool* aAllowSpdy) {
4054 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"
, 4054); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4055
4056 *aAllowSpdy = LoadAllowSpdy();
4057 return NS_OK;
4058}
4059
4060NS_IMETHODIMPnsresult
4061HttpBaseChannel::SetAllowSpdy(bool aAllowSpdy) {
4062 StoreAllowSpdy(aAllowSpdy);
4063 return NS_OK;
4064}
4065
4066NS_IMETHODIMPnsresult
4067HttpBaseChannel::GetAllowHttp3(bool* aAllowHttp3) {
4068 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"
, 4068); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4069
4070 *aAllowHttp3 = LoadAllowHttp3();
4071 return NS_OK;
4072}
4073
4074NS_IMETHODIMPnsresult
4075HttpBaseChannel::SetAllowHttp3(bool aAllowHttp3) {
4076 StoreAllowHttp3(aAllowHttp3);
4077 return NS_OK;
4078}
4079
4080NS_IMETHODIMPnsresult
4081HttpBaseChannel::GetAllowAltSvc(bool* aAllowAltSvc) {
4082 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"
, 4082); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4083
4084 *aAllowAltSvc = LoadAllowAltSvc();
4085 return NS_OK;
4086}
4087
4088NS_IMETHODIMPnsresult
4089HttpBaseChannel::SetAllowAltSvc(bool aAllowAltSvc) {
4090 StoreAllowAltSvc(aAllowAltSvc);
4091 return NS_OK;
4092}
4093
4094NS_IMETHODIMPnsresult
4095HttpBaseChannel::GetBeConservative(bool* aBeConservative) {
4096 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"
, 4096); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4097
4098 *aBeConservative = LoadBeConservative();
4099 return NS_OK;
4100}
4101
4102NS_IMETHODIMPnsresult
4103HttpBaseChannel::SetBeConservative(bool aBeConservative) {
4104 StoreBeConservative(aBeConservative);
4105 return NS_OK;
4106}
4107
4108bool HttpBaseChannel::BypassProxy() {
4109 return StaticPrefs::network_proxy_allow_bypass() && LoadBypassProxy();
4110}
4111
4112NS_IMETHODIMPnsresult
4113HttpBaseChannel::GetBypassProxy(bool* aBypassProxy) {
4114 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"
, 4114); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4115
4116 *aBypassProxy = BypassProxy();
4117 return NS_OK;
4118}
4119
4120NS_IMETHODIMPnsresult
4121HttpBaseChannel::SetBypassProxy(bool aBypassProxy) {
4122 if (StaticPrefs::network_proxy_allow_bypass()) {
4123 StoreBypassProxy(aBypassProxy);
4124 } else {
4125 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"
, 4125)
;
4126 return NS_ERROR_FAILURE;
4127 }
4128 return NS_OK;
4129}
4130
4131NS_IMETHODIMPnsresult
4132HttpBaseChannel::GetProxyDNSStrategy(
4133 nsIHttpChannelInternal::ProxyDNSStrategy* aStrategy) {
4134 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", 4134
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4135 *aStrategy = nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN;
4136 return NS_OK;
4137}
4138
4139NS_IMETHODIMPnsresult
4140HttpBaseChannel::GetIsTRRServiceChannel(bool* aIsTRRServiceChannel) {
4141 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"
, 4141); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4142
4143 *aIsTRRServiceChannel = LoadIsTRRServiceChannel();
4144 return NS_OK;
4145}
4146
4147NS_IMETHODIMPnsresult
4148HttpBaseChannel::SetIsTRRServiceChannel(bool aIsTRRServiceChannel) {
4149 StoreIsTRRServiceChannel(aIsTRRServiceChannel);
4150 return NS_OK;
4151}
4152
4153NS_IMETHODIMPnsresult
4154HttpBaseChannel::GetIsResolvedByTRR(bool* aResolvedByTRR) {
4155 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"
, 4155); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4156 *aResolvedByTRR = LoadResolvedByTRR();
4157 return NS_OK;
4158}
4159
4160NS_IMETHODIMPnsresult
4161HttpBaseChannel::GetEffectiveTRRMode(nsIRequest::TRRMode* aEffectiveTRRMode) {
4162 *aEffectiveTRRMode = mEffectiveTRRMode;
4163 return NS_OK;
4164}
4165
4166NS_IMETHODIMPnsresult
4167HttpBaseChannel::GetTrrSkipReason(nsITRRSkipReason::value* aTrrSkipReason) {
4168 *aTrrSkipReason = mTRRSkipReason;
4169 return NS_OK;
4170}
4171
4172NS_IMETHODIMPnsresult
4173HttpBaseChannel::GetIsLoadedBySocketProcess(bool* aResult) {
4174 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", 4174
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4175 *aResult = LoadLoadedBySocketProcess();
4176 return NS_OK;
4177}
4178
4179NS_IMETHODIMPnsresult
4180HttpBaseChannel::GetTlsFlags(uint32_t* aTlsFlags) {
4181 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", 4181
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4182
4183 *aTlsFlags = mTlsFlags;
4184 return NS_OK;
4185}
4186
4187NS_IMETHODIMPnsresult
4188HttpBaseChannel::SetTlsFlags(uint32_t aTlsFlags) {
4189 mTlsFlags = aTlsFlags;
4190 return NS_OK;
4191}
4192
4193NS_IMETHODIMPnsresult
4194HttpBaseChannel::GetResponseTimeoutEnabled(bool* aEnable) {
4195 if (NS_WARN_IF(!aEnable)NS_warn_if_impl(!aEnable, "!aEnable", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4195)
) {
4196 return NS_ERROR_NULL_POINTER;
4197 }
4198 *aEnable = LoadResponseTimeoutEnabled();
4199 return NS_OK;
4200}
4201
4202NS_IMETHODIMPnsresult
4203HttpBaseChannel::SetResponseTimeoutEnabled(bool aEnable) {
4204 StoreResponseTimeoutEnabled(aEnable);
4205 return NS_OK;
4206}
4207
4208NS_IMETHODIMPnsresult
4209HttpBaseChannel::GetInitialRwin(uint32_t* aRwin) {
4210 if (NS_WARN_IF(!aRwin)NS_warn_if_impl(!aRwin, "!aRwin", "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4210)
) {
4211 return NS_ERROR_NULL_POINTER;
4212 }
4213 *aRwin = mInitialRwin;
4214 return NS_OK;
4215}
4216
4217NS_IMETHODIMPnsresult
4218HttpBaseChannel::SetInitialRwin(uint32_t aRwin) {
4219 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4219); 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"
, 4219, 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"
, 4219); } } 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", 4219
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 4219); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
4220 mInitialRwin = aRwin;
4221 return NS_OK;
4222}
4223
4224NS_IMETHODIMPnsresult
4225HttpBaseChannel::ForcePending(bool aForcePending) {
4226 StoreForcePending(aForcePending);
4227 return NS_OK;
4228}
4229
4230NS_IMETHODIMPnsresult
4231HttpBaseChannel::GetLastModifiedTime(PRTime* lastModifiedTime) {
4232 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
4233 uint32_t lastMod;
4234 nsresult rv = mResponseHead->GetLastModifiedValue(&lastMod);
4235 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"
, 4235); return rv; } } while (false)
;
4236 *lastModifiedTime = lastMod;
4237 return NS_OK;
4238}
4239
4240NS_IMETHODIMPnsresult
4241HttpBaseChannel::GetCorsIncludeCredentials(bool* aInclude) {
4242 *aInclude = LoadCorsIncludeCredentials();
4243 return NS_OK;
4244}
4245
4246NS_IMETHODIMPnsresult
4247HttpBaseChannel::SetCorsIncludeCredentials(bool aInclude) {
4248 StoreCorsIncludeCredentials(aInclude);
4249 return NS_OK;
4250}
4251
4252NS_IMETHODIMPnsresult
4253HttpBaseChannel::GetRequestMode(RequestMode* aMode) {
4254 *aMode = mRequestMode;
4255 return NS_OK;
4256}
4257
4258NS_IMETHODIMPnsresult
4259HttpBaseChannel::SetRequestMode(RequestMode aMode) {
4260 mRequestMode = aMode;
4261 return NS_OK;
4262}
4263
4264NS_IMETHODIMPnsresult
4265HttpBaseChannel::GetRedirectMode(uint32_t* aMode) {
4266 *aMode = mRedirectMode;
4267 return NS_OK;
4268}
4269
4270NS_IMETHODIMPnsresult
4271HttpBaseChannel::SetRedirectMode(uint32_t aMode) {
4272 mRedirectMode = aMode;
4273 return NS_OK;
4274}
4275
4276namespace {
4277
4278bool ContainsAllFlags(uint32_t aLoadFlags, uint32_t aMask) {
4279 return (aLoadFlags & aMask) == aMask;
4280}
4281
4282} // anonymous namespace
4283
4284NS_IMETHODIMPnsresult
4285HttpBaseChannel::GetFetchCacheMode(uint32_t* aFetchCacheMode) {
4286 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"
, 4286); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4287
4288 // Otherwise try to guess an appropriate cache mode from the load flags.
4289 if (ContainsAllFlags(mLoadFlags, INHIBIT_CACHING | LOAD_BYPASS_CACHE)) {
4290 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_STORE;
4291 } else if (ContainsAllFlags(mLoadFlags, LOAD_BYPASS_CACHE)) {
4292 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_RELOAD;
4293 } else if (ContainsAllFlags(mLoadFlags, VALIDATE_ALWAYS) ||
4294 LoadForceValidateCacheContent()) {
4295 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE;
4296 } else if (ContainsAllFlags(
4297 mLoadFlags,
4298 VALIDATE_NEVER | nsICachingChannel::LOAD_ONLY_FROM_CACHE)) {
4299 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED;
4300 } else if (ContainsAllFlags(mLoadFlags, VALIDATE_NEVER)) {
4301 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE;
4302 } else {
4303 *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT;
4304 }
4305
4306 return NS_OK;
4307}
4308
4309namespace {
4310
4311void SetCacheFlags(Atomic<uint32_t, Relaxed>& aLoadFlags, uint32_t aFlags) {
4312 // First, clear any possible cache related flags
4313 uint32_t allPossibleFlags =
4314 nsIRequest::INHIBIT_CACHING | nsIRequest::LOAD_BYPASS_CACHE |
4315 nsIRequest::VALIDATE_ALWAYS | nsIRequest::LOAD_FROM_CACHE |
4316 nsICachingChannel::LOAD_ONLY_FROM_CACHE;
4317 aLoadFlags &= ~allPossibleFlags;
4318
4319 // Then set the new flags
4320 aLoadFlags |= aFlags;
4321}
4322
4323} // anonymous namespace
4324
4325NS_IMETHODIMPnsresult
4326HttpBaseChannel::SetFetchCacheMode(uint32_t aFetchCacheMode) {
4327 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 4327); 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"
, 4327, 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"
, 4327); } } 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", 4327
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 4327); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
4328
4329 // Now, set the load flags that implement each cache mode.
4330 switch (aFetchCacheMode) {
4331 case nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT:
4332 // The "default" mode means to use the http cache normally and
4333 // respect any http cache-control headers. We effectively want
4334 // to clear our cache related load flags.
4335 SetCacheFlags(mLoadFlags, 0);
4336 break;
4337 case nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_STORE:
4338 // no-store means don't consult the cache on the way to the network, and
4339 // don't store the response in the cache even if it's cacheable.
4340 SetCacheFlags(mLoadFlags, INHIBIT_CACHING | LOAD_BYPASS_CACHE);
4341 break;
4342 case nsIHttpChannelInternal::FETCH_CACHE_MODE_RELOAD:
4343 // reload means don't consult the cache on the way to the network, but
4344 // do store the response in the cache if possible.
4345 SetCacheFlags(mLoadFlags, LOAD_BYPASS_CACHE);
4346 break;
4347 case nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE:
4348 // no-cache means always validate what's in the cache.
4349 SetCacheFlags(mLoadFlags, VALIDATE_ALWAYS);
4350 break;
4351 case nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE:
4352 // force-cache means don't validate unless if the response would vary.
4353 SetCacheFlags(mLoadFlags, VALIDATE_NEVER);
4354 break;
4355 case nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED:
4356 // only-if-cached means only from cache, no network, no validation,
4357 // generate a network error if the document was't in the cache. The
4358 // privacy implications of these flags (making it fast/easy to check if
4359 // the user has things in their cache without any network traffic side
4360 // effects) are addressed in the Request constructor which
4361 // enforces/requires same-origin request mode.
4362 SetCacheFlags(mLoadFlags,
4363 VALIDATE_NEVER | nsICachingChannel::LOAD_ONLY_FROM_CACHE);
4364 break;
4365 }
4366
4367#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
4368 uint32_t finalMode = 0;
4369 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", 4369
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(GetFetchCacheMode(&finalMode))"
")"); do { MOZ_CrashSequence(__null, 4369); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
4370 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"
, 4370); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "finalMode == aFetchCacheMode"
")"); do { MOZ_CrashSequence(__null, 4370); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4371#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED
4372
4373 return NS_OK;
4374}
4375
4376//-----------------------------------------------------------------------------
4377// HttpBaseChannel::nsISupportsPriority
4378//-----------------------------------------------------------------------------
4379
4380NS_IMETHODIMPnsresult
4381HttpBaseChannel::GetPriority(int32_t* value) {
4382 *value = mPriority;
4383 return NS_OK;
4384}
4385
4386NS_IMETHODIMPnsresult
4387HttpBaseChannel::AdjustPriority(int32_t delta) {
4388 return SetPriority(mPriority + delta);
4389}
4390
4391//-----------------------------------------------------------------------------
4392// HttpBaseChannel::nsIResumableChannel
4393//-----------------------------------------------------------------------------
4394
4395NS_IMETHODIMPnsresult
4396HttpBaseChannel::GetEntityID(nsACString& aEntityID) {
4397 // Don't return an entity ID for Non-GET requests which require
4398 // additional data
4399 if (!mRequestHead.IsGet()) {
4400 return NS_ERROR_NOT_RESUMABLE;
4401 }
4402
4403 uint64_t size = UINT64_MAX(18446744073709551615UL);
4404 nsAutoCString etag, lastmod;
4405 if (mResponseHead) {
4406 // Don't return an entity if the server sent the following header:
4407 // Accept-Ranges: none
4408 // Not sending the Accept-Ranges header means we can still try
4409 // sending range requests.
4410 nsAutoCString acceptRanges;
4411 (void)mResponseHead->GetHeader(nsHttp::Accept_Ranges, acceptRanges);
4412 if (!acceptRanges.IsEmpty() &&
4413 !nsHttp::FindToken(acceptRanges.get(), "bytes",
4414 HTTP_HEADER_VALUE_SEPS" \t" ",")) {
4415 return NS_ERROR_NOT_RESUMABLE;
4416 }
4417
4418 size = mResponseHead->TotalEntitySize();
4419 (void)mResponseHead->GetHeader(nsHttp::Last_Modified, lastmod);
4420 (void)mResponseHead->GetHeader(nsHttp::ETag, etag);
4421 }
4422 nsCString entityID;
4423 NS_EscapeURL(etag.BeginReading(), etag.Length(),
4424 esc_AlwaysCopy | esc_FileBaseName | esc_Forced, entityID);
4425 entityID.Append('/');
4426 entityID.AppendInt(int64_t(size));
4427 entityID.Append('/');
4428 entityID.Append(lastmod);
4429 // NOTE: Appending lastmod as the last part avoids having to escape it
4430
4431 aEntityID = std::move(entityID);
4432
4433 return NS_OK;
4434}
4435
4436//-----------------------------------------------------------------------------
4437// HttpBaseChannel::nsIConsoleReportCollector
4438//-----------------------------------------------------------------------------
4439
4440void HttpBaseChannel::AddConsoleReport(
4441 uint32_t aErrorFlags, const nsACString& aCategory,
4442 PropertiesFile aPropertiesFile, const nsACString& aSourceFileURI,
4443 uint32_t aLineNumber, uint32_t aColumnNumber,
4444 const nsACString& aMessageName, const nsTArray<nsString>& aStringParams) {
4445 mReportCollector->AddConsoleReport(aErrorFlags, aCategory, aPropertiesFile,
4446 aSourceFileURI, aLineNumber, aColumnNumber,
4447 aMessageName, aStringParams);
4448
4449 // If this channel is already part of a loadGroup, we can flush this console
4450 // report immediately.
4451 HttpBaseChannel::MaybeFlushConsoleReports();
4452}
4453
4454void HttpBaseChannel::FlushReportsToConsole(uint64_t aInnerWindowID,
4455 ReportAction aAction) {
4456 mReportCollector->FlushReportsToConsole(aInnerWindowID, aAction);
4457}
4458
4459void HttpBaseChannel::FlushReportsToConsoleForServiceWorkerScope(
4460 const nsACString& aScope, ReportAction aAction) {
4461 mReportCollector->FlushReportsToConsoleForServiceWorkerScope(aScope, aAction);
4462}
4463
4464void HttpBaseChannel::FlushConsoleReports(dom::Document* aDocument,
4465 ReportAction aAction) {
4466 mReportCollector->FlushConsoleReports(aDocument, aAction);
4467}
4468
4469void HttpBaseChannel::FlushConsoleReports(nsILoadGroup* aLoadGroup,
4470 ReportAction aAction) {
4471 mReportCollector->FlushConsoleReports(aLoadGroup, aAction);
4472}
4473
4474void HttpBaseChannel::FlushConsoleReports(
4475 nsIConsoleReportCollector* aCollector) {
4476 mReportCollector->FlushConsoleReports(aCollector);
4477}
4478
4479void HttpBaseChannel::StealConsoleReports(
4480 nsTArray<net::ConsoleReportCollected>& aReports) {
4481 mReportCollector->StealConsoleReports(aReports);
4482}
4483
4484void HttpBaseChannel::ClearConsoleReports() {
4485 mReportCollector->ClearConsoleReports();
4486}
4487
4488bool HttpBaseChannel::IsNavigation() {
4489 return LoadForceMainDocumentChannel() || (mLoadFlags & LOAD_DOCUMENT_URI);
4490}
4491
4492nsIPrincipal* HttpBaseChannel::GetAltDataBindingPrincipal() {
4493 if (!mLoadInfo) {
4494 return nullptr;
4495 }
4496
4497 nsIPrincipal* principal = mLoadInfo->GetLoadingPrincipal();
4498 if (!principal) {
4499 principal = mLoadInfo->TriggeringPrincipal();
4500 }
4501 return principal;
4502}
4503
4504nsresult HttpBaseChannel::GetAltDataBindingOrigin(nsACString& aOrigin) {
4505 aOrigin.Truncate();
4506 nsIPrincipal* principal = GetAltDataBindingPrincipal();
4507 if (!principal) {
4508 return NS_ERROR_FAILURE;
4509 }
4510 return principal->GetOrigin(aOrigin);
4511}
4512
4513bool HttpBaseChannel::BypassServiceWorker() const {
4514 return mLoadFlags & LOAD_BYPASS_SERVICE_WORKER;
4515}
4516
4517bool HttpBaseChannel::ShouldIntercept(nsIURI* aURI) {
4518 nsCOMPtr<nsINetworkInterceptController> controller;
4519 GetCallback(controller);
4520 bool shouldIntercept = false;
4521
4522 if (!StaticPrefs::dom_serviceWorkers_enabled()) {
4523 return false;
4524 }
4525
4526 // We should never intercept internal redirects. The ServiceWorker code
4527 // can trigger interntal redirects as the result of a FetchEvent. If
4528 // we re-intercept then an infinite loop can occur.
4529 //
4530 // Its also important that we do not set the LOAD_BYPASS_SERVICE_WORKER
4531 // flag because an internal redirect occurs. Its possible that another
4532 // interception should occur after the internal redirect. For example,
4533 // if the ServiceWorker chooses not to call respondWith() the channel
4534 // will be reset with an internal redirect. If the request is a navigation
4535 // and the network then triggers a redirect its possible the new URL
4536 // should be intercepted again.
4537 //
4538 // Note, HSTS upgrade redirects are often treated the same as internal
4539 // redirects. In this case, however, we intentionally allow interception
4540 // of HSTS upgrade redirects. This matches the expected spec behavior and
4541 // does not run the risk of infinite loops as described above.
4542 bool internalRedirect =
4543 mLastRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL;
4544
4545 if (controller && mLoadInfo && !BypassServiceWorker() && !internalRedirect) {
4546 nsresult rv = controller->ShouldPrepareForIntercept(
4547 aURI ? aURI : mURI.get(), this, &shouldIntercept);
4548 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4549 return false;
4550 }
4551 }
4552 return shouldIntercept;
4553}
4554
4555void HttpBaseChannel::AddAsNonTailRequest() {
4556 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", 4556
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 4556); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4557
4558 if (EnsureRequestContext()) {
4559 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4560 "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)
4561 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)
;
4562
4563 if (!LoadAddedAsNonTailRequest()) {
4564 mRequestContext->AddNonTailRequest();
4565 StoreAddedAsNonTailRequest(true);
4566 }
4567 }
4568}
4569
4570void HttpBaseChannel::RemoveAsNonTailRequest() {
4571 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", 4571
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 4571); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4572
4573 if (mRequestContext) {
4574 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4575 ("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)
4576 "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)
4577 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)
;
4578
4579 if (LoadAddedAsNonTailRequest()) {
4580 mRequestContext->RemoveNonTailRequest();
4581 StoreAddedAsNonTailRequest(false);
4582 }
4583 }
4584}
4585
4586#ifdef DEBUG1
4587void HttpBaseChannel::AssertPrivateBrowsingId() {
4588 nsCOMPtr<nsILoadContext> loadContext;
4589 NS_QueryNotificationCallbacks(this, loadContext);
4590
4591 if (!loadContext) {
4592 return;
4593 }
4594
4595 // We skip testing of favicon loading here since it could be triggered by XUL
4596 // image which uses SystemPrincipal. The SystemPrincpal doesn't have
4597 // mPrivateBrowsingId.
4598 if (mLoadInfo->GetLoadingPrincipal() &&
4599 mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal() &&
4600 mLoadInfo->InternalContentPolicyType() ==
4601 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
4602 return;
4603 }
4604
4605 OriginAttributes docShellAttrs;
4606 loadContext->GetOriginAttributes(docShellAttrs);
4607 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"
, 4610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
") (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")"); do { MOZ_CrashSequence(__null, 4610); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
4608 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"
, 4610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
") (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")"); do { MOZ_CrashSequence(__null, 4610); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
4609 "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"
, 4610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
") (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")"); do { MOZ_CrashSequence(__null, 4610); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
4610 "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"
, 4610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId"
") (" "PrivateBrowsingId values are not the same between LoadInfo and "
"LoadContext." ")"); do { MOZ_CrashSequence(__null, 4610); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
4611}
4612#endif
4613
4614already_AddRefed<nsILoadInfo> HttpBaseChannel::CloneLoadInfoForRedirect(
4615 nsIURI* aNewURI, uint32_t aRedirectFlags) {
4616 // make a copy of the loadinfo, append to the redirectchain
4617 // this will be set on the newly created channel for the redirect target.
4618 nsCOMPtr<nsILoadInfo> newLoadInfo =
4619 static_cast<mozilla::net::LoadInfo*>(mLoadInfo.get())->Clone();
4620
4621 ExtContentPolicyType contentPolicyType =
4622 mLoadInfo->GetExternalContentPolicyType();
4623 if (contentPolicyType == ExtContentPolicy::TYPE_DOCUMENT ||
4624 contentPolicyType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
4625 // Reset PrincipalToInherit to a null principal. We'll credit the the
4626 // redirecting resource's result principal as the new principal's precursor.
4627 // This means that a data: URI will end up loading in a process based on the
4628 // redirected-from URI.
4629 nsCOMPtr<nsIPrincipal> redirectPrincipal;
4630 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
4631 this, getter_AddRefs(redirectPrincipal));
4632 nsCOMPtr<nsIPrincipal> nullPrincipalToInherit =
4633 NullPrincipal::CreateWithInheritedAttributes(redirectPrincipal);
4634 newLoadInfo->SetTrustedPrincipalToInherit(nullPrincipalToInherit);
4635 }
4636
4637 bool isTopLevelDoc = newLoadInfo->GetExternalContentPolicyType() ==
4638 ExtContentPolicy::TYPE_DOCUMENT;
4639
4640 if (isTopLevelDoc) {
4641 // re-compute the origin attributes of the loadInfo if it's top-level load.
4642 nsCOMPtr<nsILoadContext> loadContext;
4643 NS_QueryNotificationCallbacks(this, loadContext);
4644 OriginAttributes attrs;
4645 if (loadContext) {
4646 loadContext->GetOriginAttributes(attrs);
4647 }
4648
4649 OriginAttributes channelAttrs = newLoadInfo->GetOriginAttributes();
4650
4651 // Preserve the container from the channel attributes, as it could
4652 // legitimately differ from the loadContext.
4653 attrs.mUserContextId = channelAttrs.mUserContextId;
4654
4655 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"
, 4657); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId"
") (" "docshell and necko should have the same privateBrowsingId attribute."
")"); do { MOZ_CrashSequence(__null, 4657); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4656 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"
, 4657); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId"
") (" "docshell and necko should have the same privateBrowsingId attribute."
")"); do { MOZ_CrashSequence(__null, 4657); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4657 "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"
, 4657); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mPrivateBrowsingId == channelAttrs.mPrivateBrowsingId"
") (" "docshell and necko should have the same privateBrowsingId attribute."
")"); do { MOZ_CrashSequence(__null, 4657); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4658 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"
, 4661); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
") (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")"); do { MOZ_CrashSequence(__null, 4661); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4659 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"
, 4661); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
") (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")"); do { MOZ_CrashSequence(__null, 4661); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4660 "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"
, 4661); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
") (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")"); do { MOZ_CrashSequence(__null, 4661); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4661 "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"
, 4661); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs.mGeckoViewSessionContextId == channelAttrs.mGeckoViewSessionContextId"
") (" "docshell and necko should have the same " "geckoViewSessionContextId attribute"
")"); do { MOZ_CrashSequence(__null, 4661); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4662
4663 attrs.SetFirstPartyDomain(true, aNewURI);
4664
4665 newLoadInfo->SetOriginAttributes(attrs);
4666
4667 // re-compute the upgrade insecure requests bit for document navigations
4668 // since it should only apply to same-origin navigations (redirects).
4669 // we only do this if the CSP of the triggering element (the cspToInherit)
4670 // uses 'upgrade-insecure-requests', otherwise UIR does not apply.
4671 nsCOMPtr<nsIPolicyContainer> policyContainer =
4672 newLoadInfo->GetPolicyContainerToInherit();
4673 nsCOMPtr<nsIContentSecurityPolicy> csp =
4674 PolicyContainer::GetCSP(policyContainer);
4675 if (csp) {
4676 bool upgradeInsecureRequests = false;
4677 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
4678 if (upgradeInsecureRequests) {
4679 nsCOMPtr<nsIPrincipal> resultPrincipal =
4680 BasePrincipal::CreateContentPrincipal(
4681 aNewURI, newLoadInfo->GetOriginAttributes());
4682 bool isConsideredSameOriginforUIR =
4683 nsContentSecurityUtils::IsConsideredSameOriginForUIR(
4684 newLoadInfo->TriggeringPrincipal(), resultPrincipal);
4685 static_cast<mozilla::net::LoadInfo*>(newLoadInfo.get())
4686 ->SetUpgradeInsecureRequests(isConsideredSameOriginforUIR);
4687 }
4688 }
4689 }
4690
4691 // Clone a new cookieJarSettings from the old one for the new channel.
4692 // Otherwise, updating the new cookieJarSettings will affect the old one.
4693 nsCOMPtr<nsICookieJarSettings> oldCookieJarSettings;
4694 mLoadInfo->GetCookieJarSettings(getter_AddRefs(oldCookieJarSettings));
4695
4696 RefPtr<CookieJarSettings> newCookieJarSettings;
4697 newCookieJarSettings = CookieJarSettings::Cast(oldCookieJarSettings)->Clone();
4698
4699 newLoadInfo->SetCookieJarSettings(newCookieJarSettings);
4700
4701 // Clear the isThirdPartyContextToTopWindow flag for the new channel so that
4702 // it will be computed again when the new channel is opened.
4703 static_cast<net::LoadInfo*>(newLoadInfo.get())
4704 ->ClearIsThirdPartyContextToTopWindow();
4705
4706 // Leave empty, we want a 'clean ground' when creating the new channel.
4707 // This will be ensured to be either set by the protocol handler or set
4708 // to the redirect target URI properly after the channel creation.
4709 newLoadInfo->SetResultPrincipalURI(nullptr);
4710
4711 bool isInternalRedirect =
4712 (aRedirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
4713 nsIChannelEventSink::REDIRECT_STS_UPGRADE));
4714
4715 // Reset our sandboxed null principal ID when cloning loadInfo for an
4716 // externally visible redirect.
4717 if (!isInternalRedirect) {
4718 // If we've redirected from http to something that isn't, clear
4719 // the "external" flag, as loads that now go to other apps should be
4720 // allowed to go ahead and not trip infinite-loop protection
4721 // (see bug 1717314 for context).
4722 if (!net::SchemeIsHttpOrHttps(aNewURI)) {
4723 newLoadInfo->SetLoadTriggeredFromExternal(false);
4724 }
4725 newLoadInfo->ResetSandboxedNullPrincipalID();
4726
4727 if (isTopLevelDoc) {
4728 // Reset HTTPS-first and -only status on http redirect. To not
4729 // unexpectedly downgrade requests that weren't upgraded via HTTPS-First
4730 // (Bug 1904238).
4731 (void)newLoadInfo->SetHttpsOnlyStatus(
4732 nsILoadInfo::HTTPS_ONLY_UNINITIALIZED);
4733
4734 // Reset schemeless status flag to prevent schemeless HTTPS-First from
4735 // repeatedly trying to upgrade loads that get downgraded again from the
4736 // server by a redirect (Bug 1937386).
4737 (void)newLoadInfo->SetSchemelessInput(
4738 nsILoadInfo::SchemelessInputTypeUnset);
4739 }
4740 }
4741
4742 newLoadInfo->AppendRedirectHistoryEntry(this, isInternalRedirect);
4743
4744 return newLoadInfo.forget();
4745}
4746
4747//-----------------------------------------------------------------------------
4748// nsHttpChannel::nsITraceableChannel
4749//-----------------------------------------------------------------------------
4750
4751NS_IMETHODIMPnsresult
4752HttpBaseChannel::SetNewListener(nsIStreamListener* aListener,
4753 bool aMustApplyContentConversion,
4754 nsIStreamListener** _retval) {
4755 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
4756 "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)
4757 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)
;
4758
4759 if (!LoadTracingEnabled()) return NS_ERROR_FAILURE;
4760
4761 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", 4761
); return NS_ERROR_UNEXPECTED; } } while (false)
;
4762 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", 4762
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4763
4764 nsCOMPtr<nsIStreamListener> wrapper = new nsStreamListenerWrapper(mListener);
4765
4766 wrapper.forget(_retval);
4767 mListener = aListener;
4768 if (aMustApplyContentConversion) {
4769 StoreListenerRequiresContentConversion(true);
4770 }
4771 return NS_OK;
4772}
4773
4774//-----------------------------------------------------------------------------
4775// HttpBaseChannel helpers
4776//-----------------------------------------------------------------------------
4777
4778void HttpBaseChannel::ReleaseListeners() {
4779 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"
, 4780); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentThread->IsOnCurrentThread()"
") (" "Should only be called on the current thread" ")"); do
{ MOZ_CrashSequence(__null, 4780); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
4780 "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"
, 4780); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCurrentThread->IsOnCurrentThread()"
") (" "Should only be called on the current thread" ")"); do
{ MOZ_CrashSequence(__null, 4780); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4781
4782 mListener = nullptr;
4783 mCallbacks = nullptr;
4784 mProgressSink = nullptr;
4785 mCompressListener = nullptr;
4786 mORB = nullptr;
4787}
4788
4789void HttpBaseChannel::DoNotifyListener() {
4790 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)
;
4791
4792 // In case nsHttpChannel::OnStartRequest wasn't called (e.g. due to flag
4793 // LOAD_ONLY_IF_MODIFIED) we want to set AfterOnStartRequestBegun to true
4794 // before notifying listener.
4795 if (!LoadAfterOnStartRequestBegun()) {
4796 StoreAfterOnStartRequestBegun(true);
4797 }
4798
4799 if (mListener && !LoadOnStartRequestCalled()) {
4800 nsCOMPtr<nsIStreamListener> listener = mListener;
4801 StoreOnStartRequestCalled(true);
4802 listener->OnStartRequest(this);
4803 }
4804 StoreOnStartRequestCalled(true);
4805
4806 // Make sure IsPending is set to false. At this moment we are done from
4807 // the point of view of our consumer and we have to report our self
4808 // as not-pending.
4809 StoreIsPending(false);
4810
4811 // notify "http-on-before-stop-request" observers
4812 gHttpHandler->OnBeforeStopRequest(this);
4813
4814 if (mListener && !LoadOnStopRequestCalled()) {
4815 nsCOMPtr<nsIStreamListener> listener = mListener;
4816 StoreOnStopRequestCalled(true);
4817 listener->OnStopRequest(this, mStatus);
4818 }
4819 StoreOnStopRequestCalled(true);
4820
4821 // notify "http-on-stop-request" observers
4822 gHttpHandler->OnStopRequest(this);
4823
4824 // This channel has finished its job, potentially release any tail-blocked
4825 // requests with this.
4826 RemoveAsNonTailRequest();
4827
4828 // We have to make sure to drop the references to listeners and callbacks
4829 // no longer needed.
4830 ReleaseListeners();
4831
4832 DoNotifyListenerCleanup();
4833
4834 // If this is a navigation, then we must let the docshell flush the reports
4835 // to the console later. The LoadDocument() is pointing at the detached
4836 // document that started the navigation. We want to show the reports on the
4837 // new document. Otherwise the console is wiped and the user never sees
4838 // the information.
4839 if (!IsNavigation()) {
4840 if (mLoadGroup) {
4841 FlushConsoleReports(mLoadGroup);
4842 } else {
4843 RefPtr<dom::Document> doc;
4844 mLoadInfo->GetLoadingDocument(getter_AddRefs(doc));
4845 FlushConsoleReports(doc);
4846 }
4847 }
4848}
4849
4850void HttpBaseChannel::AddCookiesToRequest() {
4851 if (mLoadFlags & LOAD_ANONYMOUS) {
4852 return;
4853 }
4854
4855 bool useCookieService = (XRE_IsParentProcess());
4856 nsAutoCString cookie;
4857 if (useCookieService) {
4858 nsICookieService* cs = gHttpHandler->GetCookieService();
4859 if (cs) {
4860 cs->GetCookieStringFromHttp(mURI, this, cookie);
4861 }
4862
4863 if (cookie.IsEmpty()) {
4864 cookie = mUserSetCookieHeader;
4865 } else if (!mUserSetCookieHeader.IsEmpty()) {
4866 cookie.AppendLiteral("; ");
4867 cookie.Append(mUserSetCookieHeader);
4868 }
4869 } else {
4870 cookie = mUserSetCookieHeader;
4871 }
4872
4873 // If we are in the child process, we want the parent seeing any
4874 // cookie headers that might have been set by SetRequestHeader()
4875 SetRequestHeader(nsHttp::Cookie.val(), cookie, false);
4876}
4877
4878/* static */
4879void HttpBaseChannel::PropagateReferenceIfNeeded(
4880 nsIURI* aURI, nsCOMPtr<nsIURI>& aRedirectURI) {
4881 bool hasRef = false;
4882 nsresult rv = aRedirectURI->GetHasRef(&hasRef);
4883 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !hasRef) {
4884 nsAutoCString ref;
4885 aURI->GetRef(ref);
4886 if (!ref.IsEmpty()) {
4887 // NOTE: SetRef will fail if mRedirectURI is immutable
4888 // (e.g. an about: URI)... Oh well.
4889 (void)NS_MutateURI(aRedirectURI).SetRef(ref).Finalize(aRedirectURI);
4890 }
4891 }
4892}
4893
4894bool HttpBaseChannel::ShouldRewriteRedirectToGET(
4895 uint32_t httpStatus, nsHttpRequestHead::ParsedMethodType method) {
4896 // for 301 and 302, only rewrite POST
4897 if (httpStatus == 301 || httpStatus == 302) {
4898 return method == nsHttpRequestHead::kMethod_Post;
4899 }
4900
4901 // rewrite for 303 unless it was HEAD
4902 if (httpStatus == 303) return method != nsHttpRequestHead::kMethod_Head;
4903
4904 // otherwise, such as for 307, do not rewrite
4905 return false;
4906}
4907
4908NS_IMETHODIMPnsresult
4909HttpBaseChannel::ShouldStripRequestBodyHeader(const nsACString& aMethod,
4910 bool* aResult) {
4911 *aResult = false;
4912 uint32_t httpStatus = 0;
4913 if (NS_FAILED(GetResponseStatus(&httpStatus))((bool)(__builtin_expect(!!(NS_FAILED_impl(GetResponseStatus(
&httpStatus))), 0)))
) {
4914 return NS_OK;
4915 }
4916
4917 nsAutoCString method(aMethod);
4918 nsHttpRequestHead::ParsedMethodType parsedMethod;
4919 nsHttpRequestHead::ParseMethod(method, parsedMethod);
4920 // Fetch 4.4.11, which is slightly different than the perserved method
4921 // algrorithm: strip request-body-header for GET->GET redirection for 303.
4922 *aResult =
4923 ShouldRewriteRedirectToGET(httpStatus, parsedMethod) &&
4924 !(httpStatus == 303 && parsedMethod == nsHttpRequestHead::kMethod_Get);
4925
4926 return NS_OK;
4927}
4928
4929HttpBaseChannel::ReplacementChannelConfig
4930HttpBaseChannel::CloneReplacementChannelConfig(bool aPreserveMethod,
4931 uint32_t aRedirectFlags,
4932 ReplacementReason aReason) {
4933 ReplacementChannelConfig config;
4934 config.redirectFlags = aRedirectFlags;
4935 config.classOfService = mClassOfService;
4936
4937 if (mPrivateBrowsingOverriden) {
4938 config.privateBrowsing = Some(mPrivateBrowsing);
4939 }
4940
4941 if (mReferrerInfo) {
4942 // When cloning for a document channel replacement (parent process
4943 // copying values for a new content process channel), this happens after
4944 // OnStartRequest so we have the headers for the response available.
4945 // We don't want to apply them to the referrer for the channel though,
4946 // since that is the referrer for the current document, and the header
4947 // should only apply to navigations from the current document.
4948 if (aReason == ReplacementReason::DocumentChannel) {
4949 config.referrerInfo = mReferrerInfo;
4950 } else {
4951 dom::ReferrerPolicy referrerPolicy = dom::ReferrerPolicy::_empty;
4952 nsAutoCString tRPHeaderCValue;
4953 (void)GetResponseHeader("referrer-policy"_ns, tRPHeaderCValue);
4954 NS_ConvertUTF8toUTF16 tRPHeaderValue(tRPHeaderCValue);
4955
4956 if (!tRPHeaderValue.IsEmpty()) {
4957 referrerPolicy =
4958 dom::ReferrerInfo::ReferrerPolicyFromHeaderString(tRPHeaderValue);
4959 }
4960
4961 // In case we are here because an upgrade happened through mixed content
4962 // upgrading, CSP upgrade-insecure-requests, HTTPS-Only or HTTPS-First, we
4963 // have to recalculate the referrer based on the original referrer to
4964 // account for the different scheme. This does NOT apply to HSTS.
4965 // See Bug 1857894 and order of https://fetch.spec.whatwg.org/#main-fetch.
4966 // Otherwise, if we have a new referrer policy, we want to recalculate the
4967 // referrer based on the old computed referrer (Bug 1678545).
4968 bool wasNonHSTSUpgrade =
4969 (aRedirectFlags & nsIChannelEventSink::REDIRECT_STS_UPGRADE) &&
4970 (!mLoadInfo->GetHstsStatus());
4971 if (wasNonHSTSUpgrade) {
4972 nsCOMPtr<nsIURI> referrer = mReferrerInfo->GetOriginalReferrer();
4973 config.referrerInfo =
4974 new dom::ReferrerInfo(referrer, mReferrerInfo->ReferrerPolicy(),
4975 mReferrerInfo->GetSendReferrer());
4976 } else if (referrerPolicy != dom::ReferrerPolicy::_empty) {
4977 nsCOMPtr<nsIURI> referrer = mReferrerInfo->GetComputedReferrer();
4978 config.referrerInfo = new dom::ReferrerInfo(
4979 referrer, referrerPolicy, mReferrerInfo->GetSendReferrer());
4980 } else {
4981 config.referrerInfo = mReferrerInfo;
4982 }
4983 }
4984 }
4985
4986 nsCOMPtr<nsITimedChannel> oldTimedChannel(
4987 do_QueryInterface(static_cast<nsIHttpChannel*>(this)));
4988 if (oldTimedChannel) {
4989 config.timedChannelInfo = Some(dom::TimedChannelInfo());
4990 config.timedChannelInfo->redirectCount() = mRedirectCount;
4991 config.timedChannelInfo->internalRedirectCount() = mInternalRedirectCount;
4992 config.timedChannelInfo->asyncOpen() = mAsyncOpenTime;
4993 config.timedChannelInfo->channelCreation() = mChannelCreationTimestamp;
4994 config.timedChannelInfo->redirectStart() = mRedirectStartTimeStamp;
4995 config.timedChannelInfo->redirectEnd() = mRedirectEndTimeStamp;
4996 config.timedChannelInfo->initiatorType() = mInitiatorType;
4997 config.timedChannelInfo->allRedirectsSameOrigin() =
4998 LoadAllRedirectsSameOrigin();
4999 config.timedChannelInfo->allRedirectsSameOriginIgnoringInternal() =
5000 LoadAllRedirectsSameOriginIgnoringInternal();
5001 config.timedChannelInfo->allRedirectsPassTimingAllowCheck() =
5002 LoadAllRedirectsPassTimingAllowCheck();
5003 // Execute the timing allow check to determine whether
5004 // to report the redirect timing info
5005 nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
5006 // TYPE_DOCUMENT loads don't have a loadingPrincipal, so we can't set
5007 // AllRedirectsPassTimingAllowCheck on them.
5008 if (loadInfo->GetExternalContentPolicyType() !=
5009 ExtContentPolicy::TYPE_DOCUMENT) {
5010 nsCOMPtr<nsIPrincipal> principal = loadInfo->GetLoadingPrincipal();
5011 config.timedChannelInfo->timingAllowCheckForPrincipal() =
5012 Some(oldTimedChannel->TimingAllowCheck(principal));
5013 }
5014
5015 config.timedChannelInfo->allRedirectsPassTimingAllowCheck() =
5016 LoadAllRedirectsPassTimingAllowCheck();
5017 config.timedChannelInfo->launchServiceWorkerStart() =
5018 mLaunchServiceWorkerStart;
5019 config.timedChannelInfo->launchServiceWorkerEnd() = mLaunchServiceWorkerEnd;
5020 config.timedChannelInfo->dispatchFetchEventStart() =
5021 mDispatchFetchEventStart;
5022 config.timedChannelInfo->dispatchFetchEventEnd() = mDispatchFetchEventEnd;
5023 config.timedChannelInfo->handleFetchEventStart() = mHandleFetchEventStart;
5024 config.timedChannelInfo->handleFetchEventEnd() = mHandleFetchEventEnd;
5025 config.timedChannelInfo->responseStart() =
5026 mTransactionTimings.responseStart;
5027 config.timedChannelInfo->responseEnd() = mTransactionTimings.responseEnd;
5028 }
5029
5030 if (aPreserveMethod) {
5031 // since preserveMethod is true, we need to ensure that the appropriate
5032 // request method gets set on the channel, regardless of whether or not
5033 // we set the upload stream above. This means SetRequestMethod() will
5034 // be called twice if ExplicitSetUploadStream() gets called above.
5035
5036 nsAutoCString method;
5037 mRequestHead.Method(method);
5038 config.method = Some(method);
5039
5040 if (mUploadStream) {
5041 // rewind upload stream
5042 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
5043 if (seekable) {
5044 seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
5045 }
5046 config.uploadStream = mUploadStream;
5047 }
5048 config.uploadStreamLength = mReqContentLength;
5049 config.uploadStreamIsStreaming = LoadUploadStreamIsStreaming();
5050
5051 nsAutoCString contentType;
5052 nsresult rv = mRequestHead.GetHeader(nsHttp::Content_Type, contentType);
5053 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5054 config.contentType = Some(contentType);
5055 }
5056
5057 nsAutoCString contentLength;
5058 rv = mRequestHead.GetHeader(nsHttp::Content_Length, contentLength);
5059 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5060 config.contentLength = Some(contentLength);
5061 }
5062 }
5063
5064 return config;
5065}
5066
5067/* static */ void HttpBaseChannel::ConfigureReplacementChannel(
5068 nsIChannel* newChannel, const ReplacementChannelConfig& config,
5069 ReplacementReason aReason) {
5070 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(newChannel));
5071 if (cos) {
5072 cos->SetClassOfService(config.classOfService);
5073 }
5074
5075 // Try to preserve the privacy bit if it has been overridden
5076 if (config.privateBrowsing) {
5077 nsCOMPtr<nsIPrivateBrowsingChannel> newPBChannel =
5078 do_QueryInterface(newChannel);
5079 if (newPBChannel) {
5080 newPBChannel->SetPrivate(*config.privateBrowsing);
5081 }
5082 }
5083
5084 // Transfer the timing data (if we are dealing with an nsITimedChannel).
5085 nsCOMPtr<nsITimedChannel> newTimedChannel(do_QueryInterface(newChannel));
5086 if (config.timedChannelInfo && newTimedChannel) {
5087 // If we're an internal redirect, or a document channel replacement,
5088 // then we shouldn't record any new timing for this and just copy
5089 // over the existing values.
5090 bool shouldHideTiming = aReason != ReplacementReason::Redirect;
5091 if (shouldHideTiming) {
5092 newTimedChannel->SetRedirectCount(
5093 config.timedChannelInfo->redirectCount());
5094 int32_t newCount = config.timedChannelInfo->internalRedirectCount() + 1;
5095 newTimedChannel->SetInternalRedirectCount(std::max(
5096 newCount, static_cast<int32_t>(
5097 config.timedChannelInfo->internalRedirectCount())));
5098 } else {
5099 int32_t newCount = config.timedChannelInfo->redirectCount() + 1;
5100 newTimedChannel->SetRedirectCount(std::max(
5101 newCount,
5102 static_cast<int32_t>(config.timedChannelInfo->redirectCount())));
5103 newTimedChannel->SetInternalRedirectCount(
5104 config.timedChannelInfo->internalRedirectCount());
5105 }
5106
5107 if (shouldHideTiming) {
5108 if (!config.timedChannelInfo->channelCreation().IsNull()) {
5109 newTimedChannel->SetChannelCreation(
5110 config.timedChannelInfo->channelCreation());
5111 }
5112
5113 if (!config.timedChannelInfo->asyncOpen().IsNull()) {
5114 newTimedChannel->SetAsyncOpen(config.timedChannelInfo->asyncOpen());
5115 }
5116 }
5117
5118 // If the RedirectStart is null, we will use the AsyncOpen value of the
5119 // previous channel (this is the first redirect in the redirects chain).
5120 if (config.timedChannelInfo->redirectStart().IsNull()) {
5121 // Only do this for real redirects. Internal redirects should be hidden.
5122 if (!shouldHideTiming) {
5123 newTimedChannel->SetRedirectStart(config.timedChannelInfo->asyncOpen());
5124 }
5125 } else {
5126 newTimedChannel->SetRedirectStart(
5127 config.timedChannelInfo->redirectStart());
5128 }
5129
5130 // For internal redirects just propagate the last redirect end time
5131 // forward. Otherwise the new redirect end time is the last response
5132 // end time.
5133 TimeStamp newRedirectEnd;
5134 if (shouldHideTiming) {
5135 newRedirectEnd = config.timedChannelInfo->redirectEnd();
5136 } else if (!config.timedChannelInfo->responseEnd().IsNull()) {
5137 newRedirectEnd = config.timedChannelInfo->responseEnd();
5138 } else {
5139 newRedirectEnd = TimeStamp::Now();
5140 }
5141 newTimedChannel->SetRedirectEnd(newRedirectEnd);
5142
5143 newTimedChannel->SetInitiatorType(config.timedChannelInfo->initiatorType());
5144
5145 nsCOMPtr<nsILoadInfo> loadInfo = newChannel->LoadInfo();
5146 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"
, 5146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadInfo" ")"
); do { MOZ_CrashSequence(__null, 5146); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5147
5148 newTimedChannel->SetAllRedirectsSameOrigin(
5149 config.timedChannelInfo->allRedirectsSameOrigin());
5150 newTimedChannel->SetAllRedirectsSameOriginIgnoringInternal(
5151 config.timedChannelInfo->allRedirectsSameOriginIgnoringInternal());
5152
5153 if (config.timedChannelInfo->timingAllowCheckForPrincipal()) {
5154 newTimedChannel->SetAllRedirectsPassTimingAllowCheck(
5155 config.timedChannelInfo->allRedirectsPassTimingAllowCheck() &&
5156 *config.timedChannelInfo->timingAllowCheckForPrincipal());
5157 }
5158
5159 // Propagate service worker measurements across redirects. The
5160 // PeformanceResourceTiming.workerStart API expects to see the
5161 // worker start time after a redirect.
5162 newTimedChannel->SetLaunchServiceWorkerStart(
5163 config.timedChannelInfo->launchServiceWorkerStart());
5164 newTimedChannel->SetLaunchServiceWorkerEnd(
5165 config.timedChannelInfo->launchServiceWorkerEnd());
5166 newTimedChannel->SetDispatchFetchEventStart(
5167 config.timedChannelInfo->dispatchFetchEventStart());
5168 newTimedChannel->SetDispatchFetchEventEnd(
5169 config.timedChannelInfo->dispatchFetchEventEnd());
5170 newTimedChannel->SetHandleFetchEventStart(
5171 config.timedChannelInfo->handleFetchEventStart());
5172 newTimedChannel->SetHandleFetchEventEnd(
5173 config.timedChannelInfo->handleFetchEventEnd());
5174 }
5175
5176 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
5177 if (!httpChannel) {
5178 return; // no other options to set
5179 }
5180
5181 if (config.uploadStream) {
5182 nsCOMPtr<nsIUploadChannel2> uploadChannel2 = do_QueryInterface(httpChannel);
5183 // replicate original call to SetUploadStream...
5184 if (uploadChannel2) {
5185 const nsACString& ctype =
5186 config.contentType ? *config.contentType : VoidCString();
5187 // If header is not present mRequestHead.HasHeaderValue will truncated
5188 // it. But we want to end up with a void string, not an empty string,
5189 // because ExplicitSetUploadStream treats the former as "no header" and
5190 // the latter as "header with empty string value".
5191 const nsACString& method = config.method ? *config.method : VoidCString();
5192 if (config.uploadStreamIsStreaming) {
5193 RefPtr<HttpBaseChannel> baseChan = do_QueryObject(httpChannel);
5194 if (baseChan) {
5195 baseChan->SetUploadStreamIsStreaming(true);
5196 }
5197 }
5198 uploadChannel2->ExplicitSetUploadStream(
5199 config.uploadStream, ctype, config.uploadStreamLength, method);
5200 } else if (nsCOMPtr<nsIUploadChannel> uploadChannel =
5201 do_QueryInterface(httpChannel)) {
5202 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"
, 5203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Should not QI to nsIUploadChannel but not nsIUploadChannel2"
")"); do { MOZ_CrashSequence(__null, 5203); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5203 "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"
, 5203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Should not QI to nsIUploadChannel but not nsIUploadChannel2"
")"); do { MOZ_CrashSequence(__null, 5203); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5204 }
5205 }
5206
5207 if (config.referrerInfo) {
5208 DebugOnly<nsresult> success{};
5209 success = httpChannel->SetReferrerInfo(config.referrerInfo);
5210 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", 5210
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5210); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5211 }
5212
5213 if (config.method) {
5214 DebugOnly<nsresult> rv = httpChannel->SetRequestMethod(*config.method);
5215 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"
, 5215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5215); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5216 }
5217}
5218
5219HttpBaseChannel::ReplacementChannelConfig::ReplacementChannelConfig(
5220 const dom::ReplacementChannelConfigInit& aInit) {
5221 redirectFlags = aInit.redirectFlags();
5222 classOfService = aInit.classOfService();
5223 privateBrowsing = aInit.privateBrowsing();
5224 method = aInit.method();
5225 referrerInfo = aInit.referrerInfo();
5226 timedChannelInfo = aInit.timedChannelInfo();
5227 uploadStream = aInit.uploadStream();
5228 uploadStreamLength = aInit.uploadStreamLength();
5229 uploadStreamIsStreaming = aInit.uploadStreamIsStreaming();
5230 contentType = aInit.contentType();
5231 contentLength = aInit.contentLength();
5232}
5233
5234dom::ReplacementChannelConfigInit
5235HttpBaseChannel::ReplacementChannelConfig::Serialize() {
5236 dom::ReplacementChannelConfigInit config;
5237 config.redirectFlags() = redirectFlags;
5238 config.classOfService() = classOfService;
5239 config.privateBrowsing() = privateBrowsing;
5240 config.method() = method;
5241 config.referrerInfo() = referrerInfo;
5242 config.timedChannelInfo() = timedChannelInfo;
5243 config.uploadStream() =
5244 uploadStream ? RemoteLazyInputStream::WrapStream(uploadStream) : nullptr;
5245 config.uploadStreamLength() = uploadStreamLength;
5246 config.uploadStreamIsStreaming() = uploadStreamIsStreaming;
5247 config.contentType() = contentType;
5248 config.contentLength() = contentLength;
5249
5250 return config;
5251}
5252
5253nsresult HttpBaseChannel::SetupReplacementChannel(nsIURI* newURI,
5254 nsIChannel* newChannel,
5255 bool preserveMethod,
5256 uint32_t redirectFlags) {
5257 nsresult rv;
5258
5259 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
5260 ("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)
5261 "[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)
5262 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)
;
5263
5264 // Ensure the channel's loadInfo's result principal URI so that it's
5265 // either non-null or updated to the redirect target URI.
5266 // We must do this because in case the loadInfo's result principal URI
5267 // is null, it would be taken from OriginalURI of the channel. But we
5268 // overwrite it with the whole redirect chain first URI before opening
5269 // the target channel, hence the information would be lost.
5270 // If the protocol handler that created the channel wants to use
5271 // the originalURI of the channel as the principal URI, this fulfills
5272 // that request - newURI is the original URI of the channel.
5273 nsCOMPtr<nsILoadInfo> newLoadInfo = newChannel->LoadInfo();
5274 nsCOMPtr<nsIURI> resultPrincipalURI;
5275 rv = newLoadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
5276 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"
, 5276); return rv; } } while (false)
;
5277 if (!resultPrincipalURI) {
5278 rv = newLoadInfo->SetResultPrincipalURI(newURI);
5279 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"
, 5279); return rv; } } while (false)
;
5280 }
5281
5282 nsLoadFlags loadFlags = mLoadFlags;
5283 loadFlags |= LOAD_REPLACE;
5284
5285 // if the original channel was using SSL and this channel is not using
5286 // SSL, then no need to inhibit persistent caching. however, if the
5287 // original channel was not using SSL and has INHIBIT_PERSISTENT_CACHING
5288 // set, then allow the flag to apply to the redirected channel as well.
5289 // since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
5290 // we only need to check if the original channel was using SSL.
5291 if (mURI->SchemeIs("https")) {
5292 loadFlags &= ~INHIBIT_PERSISTENT_CACHING;
5293 }
5294
5295 newChannel->SetLoadFlags(loadFlags);
5296
5297 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
5298
5299 ReplacementReason redirectType =
5300 redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
5301 nsIChannelEventSink::REDIRECT_TRANSPARENT)
5302 ? ReplacementReason::InternalRedirect
5303 : ReplacementReason::Redirect;
5304 ReplacementChannelConfig config = CloneReplacementChannelConfig(
5305 preserveMethod, redirectFlags, redirectType);
5306 ConfigureReplacementChannel(newChannel, config, redirectType);
5307
5308 // Check whether or not this was a cross-domain redirect.
5309 nsCOMPtr<nsITimedChannel> newTimedChannel(do_QueryInterface(newChannel));
5310 bool sameOriginWithOriginalUri = SameOriginWithOriginalUri(newURI);
5311 if (config.timedChannelInfo && newTimedChannel) {
5312 newTimedChannel->SetAllRedirectsSameOrigin(
5313 config.timedChannelInfo->allRedirectsSameOrigin() &&
5314 sameOriginWithOriginalUri);
5315 // Internal redirects (e.g. a service worker serving a response from a
5316 // different URL) are not real cross-origin network hops, so they must not
5317 // count as cross-origin for canvas/CSS/media tainting.
5318 newTimedChannel->SetAllRedirectsSameOriginIgnoringInternal(
5319 config.timedChannelInfo->allRedirectsSameOriginIgnoringInternal() &&
5320 (redirectType == ReplacementReason::InternalRedirect ||
5321 sameOriginWithOriginalUri));
5322 }
5323
5324 newChannel->SetLoadGroup(mLoadGroup);
5325 newChannel->SetNotificationCallbacks(mCallbacks);
5326
5327 // Console reports that could not be flushed yet, because the document being
5328 // loaded does not exist, must follow the load to the redirected channel.
5329 nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(newChannel);
5330 if (reporter) {
5331 FlushConsoleReports(reporter);
5332 }
5333
5334 // TODO: create tests for cross-origin redirect in bug 1662896.
5335 if (sameOriginWithOriginalUri) {
5336 newChannel->SetContentDisposition(mContentDispositionHint);
5337 if (mContentDispositionFilename) {
5338 newChannel->SetContentDispositionFilename(*mContentDispositionFilename);
5339 }
5340 }
5341
5342 if (!httpChannel) return NS_OK; // no other options to set
5343
5344 // Preserve the CORS preflight information.
5345 nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
5346 if (httpInternal) {
5347 httpInternal->SetLastRedirectFlags(redirectFlags);
5348
5349 if (LoadRequireCORSPreflight()) {
5350 httpInternal->SetCorsPreflightParameters(mUnsafeHeaders, false, false);
5351 }
5352 }
5353
5354 rv = httpChannel->SetAllowSTS(LoadAllowSTS());
5355 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"
, 5355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5355); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5356
5357 // convey the Accept header value
5358 {
5359 nsAutoCString oldAcceptValue;
5360 nsresult hasHeader = mRequestHead.GetHeader(nsHttp::Accept, oldAcceptValue);
5361 if (NS_SUCCEEDED(hasHeader)((bool)(__builtin_expect(!!(!NS_FAILED_impl(hasHeader)), 1)))) {
5362 rv = httpChannel->SetRequestHeader("Accept"_ns, oldAcceptValue, false);
5363 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"
, 5363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5363); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5364 }
5365 }
5366
5367 // convey the User-Agent header value
5368 // since we might be setting custom user agent from DevTools.
5369 if (httpInternal && mRequestMode == RequestMode::No_cors &&
5370 redirectType == ReplacementReason::Redirect) {
5371 nsAutoCString oldUserAgent;
5372 nsresult hasHeader =
5373 mRequestHead.GetHeader(nsHttp::User_Agent, oldUserAgent);
5374 if (NS_SUCCEEDED(hasHeader)((bool)(__builtin_expect(!!(!NS_FAILED_impl(hasHeader)), 1)))) {
5375 rv = httpChannel->SetRequestHeader("User-Agent"_ns, oldUserAgent, false);
5376 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"
, 5376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5377 }
5378 }
5379
5380 // convery the IsUserAgentHeaderModified value.
5381 if (httpInternal) {
5382 rv = httpInternal->SetIsUserAgentHeaderModified(
5383 LoadIsUserAgentHeaderModified());
5384 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"
, 5384); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5384); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5385 }
5386
5387 // share the request context - see bug 1236650
5388 rv = httpChannel->SetRequestContextID(mRequestContextID);
5389 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"
, 5389); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5389); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5390
5391 // When on the parent process, the channel can't attempt to get it itself.
5392 // When on the child process, it would be waste to query it again.
5393 rv = httpChannel->SetBrowserId(mBrowserId);
5394 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"
, 5394); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5394); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5395
5396 // Not setting this flag would break carrying permissions down to the child
5397 // process when the channel is artificially forced to be a main document load.
5398 rv = httpChannel->SetIsMainDocumentChannel(LoadForceMainDocumentChannel());
5399 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"
, 5399); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5399); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5400
5401 // Preserve the loading order
5402 nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(newChannel);
5403 if (p) {
5404 p->SetPriority(mPriority);
5405 }
5406
5407 if (httpInternal) {
5408 // Convey third party cookie, conservative, and spdy flags.
5409 rv = httpInternal->SetThirdPartyFlags(LoadThirdPartyFlags());
5410 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"
, 5410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5410); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5411 rv = httpInternal->SetAllowSpdy(LoadAllowSpdy());
5412 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"
, 5412); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5412); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5413 rv = httpInternal->SetAllowHttp3(LoadAllowHttp3());
5414 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"
, 5414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5414); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5415 rv = httpInternal->SetAllowAltSvc(LoadAllowAltSvc());
5416 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"
, 5416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5416); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5417 rv = httpInternal->SetBeConservative(LoadBeConservative());
5418 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"
, 5418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5418); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5419 rv = httpInternal->SetIsTRRServiceChannel(LoadIsTRRServiceChannel());
5420 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"
, 5420); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5420); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5421 rv = httpInternal->SetTlsFlags(mTlsFlags);
5422 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"
, 5422); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5422); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5423
5424 // Ensure the type of realChannel involves all types it may redirect to.
5425 // Such as nsHttpChannel and InterceptedChannel.
5426 // Even thought InterceptedChannel itself doesn't require these information,
5427 // it may still be necessary for the following redirections.
5428 // E.g. nsHttpChannel -> InterceptedChannel -> nsHttpChannel
5429 RefPtr<HttpBaseChannel> realChannel;
5430 CallQueryInterface(newChannel, realChannel.StartAssignment());
5431 if (realChannel) {
5432 realChannel->SetTopWindowURI(mTopWindowURI);
5433
5434 realChannel->StoreTaintedOriginFlag(
5435 ShouldTaintReplacementChannelOrigin(newChannel, redirectFlags));
5436 }
5437
5438 // update the DocumentURI indicator since we are being redirected.
5439 // if this was a top-level document channel, then the new channel
5440 // should have its mDocumentURI point to newURI; otherwise, we
5441 // just need to pass along our mDocumentURI to the new channel.
5442 if (newURI && (mURI == mDocumentURI)) {
5443 rv = httpInternal->SetDocumentURI(newURI);
5444 } else {
5445 rv = httpInternal->SetDocumentURI(mDocumentURI);
5446 }
5447 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"
, 5447); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5447); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5448
5449 // if there is a chain of keys for redirect-responses we transfer it to
5450 // the new channel (see bug #561276)
5451 {
5452 auto redirectedCachekeys = mRedirectedCachekeys.Lock();
5453 auto& ref = redirectedCachekeys.ref();
5454 if (ref) {
5455 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
5456 ("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)
5457 "[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)
5458 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
5459 rv = httpInternal->SetCacheKeysRedirectChain(ref.release());
5460 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"
, 5460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5460); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5461 }
5462 }
5463
5464 // Preserve Request mode.
5465 rv = httpInternal->SetRequestMode(mRequestMode);
5466 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"
, 5466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5466); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5467
5468 // Preserve Redirect mode flag.
5469 rv = httpInternal->SetRedirectMode(mRedirectMode);
5470 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"
, 5470); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5470); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5471
5472 httpInternal->SetAltDataForChild(LoadAltDataForChild());
5473 if (LoadDisableAltDataCache()) {
5474 httpInternal->DisableAltDataCache();
5475 }
5476 }
5477
5478 // transfer any properties
5479 nsCOMPtr<nsIWritablePropertyBag> bag(do_QueryInterface(newChannel));
5480 if (bag) {
5481 for (const auto& entry : mPropertyHash) {
5482 bag->SetProperty(entry.GetKey(), entry.GetWeak());
5483 }
5484 }
5485
5486 // Pass the preferred alt-data type on to the new channel.
5487 nsCOMPtr<nsICacheInfoChannel> cacheInfoChan(do_QueryInterface(newChannel));
5488 if (cacheInfoChan) {
5489 for (auto& data : mPreferredCachedAltDataTypes) {
5490 cacheInfoChan->PreferAlternativeDataType(data.type(), data.contentType(),
5491 data.deliverAltData());
5492 }
5493
5494 if (LoadForceValidateCacheContent()) {
5495 (void)cacheInfoChan->SetForceValidateCacheContent(true);
5496 }
5497 }
5498
5499 if (redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
5500 nsIChannelEventSink::REDIRECT_STS_UPGRADE)) {
5501 // Copy non-origin related headers to the new channel.
5502 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
5503 new AddHeadersToChannelVisitor(httpChannel);
5504 rv = mRequestHead.VisitHeaders(visitor);
5505 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"
, 5505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5505); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5506 }
5507
5508 // we need to strip Authentication headers for cross-origin requests
5509 // Ref: https://fetch.spec.whatwg.org/#http-redirect-fetch
5510 nsAutoCString authHeader;
5511 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(httpChannel->GetRequestHeader
("Authorization"_ns, authHeader))), 1)))
5512 httpChannel->GetRequestHeader("Authorization"_ns, authHeader))((bool)(__builtin_expect(!!(!NS_FAILED_impl(httpChannel->GetRequestHeader
("Authorization"_ns, authHeader))), 1)))
&&
5513 NS_ShouldRemoveAuthHeaderOnRedirect(static_cast<nsIChannel*>(this),
5514 newChannel, redirectFlags)) {
5515 rv = httpChannel->SetRequestHeader("Authorization"_ns, ""_ns, false);
5516 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"
, 5516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5516); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5517 }
5518
5519 return NS_OK;
5520}
5521
5522// check whether the new channel is of same origin as the current channel
5523bool HttpBaseChannel::IsNewChannelSameOrigin(nsIChannel* aNewChannel) {
5524 bool isSameOrigin = false;
5525 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5526
5527 if (!ssm) {
5528 return false;
5529 }
5530
5531 nsCOMPtr<nsIURI> newURI;
5532 NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(newURI));
5533
5534 nsresult rv = ssm->CheckSameOriginURI(newURI, mURI, false, false);
5535 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5536 isSameOrigin = true;
5537 }
5538
5539 return isSameOrigin;
5540}
5541
5542bool HttpBaseChannel::ShouldTaintReplacementChannelOrigin(
5543 nsIChannel* aNewChannel, uint32_t aRedirectFlags) {
5544 if (LoadTaintedOriginFlag()) {
5545 return true;
5546 }
5547
5548 if (NS_IsInternalSameURIRedirect(this, aNewChannel, aRedirectFlags) ||
5549 NS_IsHSTSUpgradeRedirect(this, aNewChannel, aRedirectFlags)) {
5550 return false;
5551 }
5552
5553 // Fetch spec "compute redirect-taint":
5554 // Taint if url's origin is not same-origin with lastURL's origin AND
5555 // request's origin is not same-origin with lastURL's origin.
5556 // Condition 1: same-origin redirect never taints.
5557 if (IsNewChannelSameOrigin(aNewChannel)) {
5558 return false;
5559 }
5560
5561 // Condition 2: cross-origin redirect — taint if the origin that initiated
5562 // the request is not same-origin with the current URL (mURI).
5563 //
5564 // Bug 1965430: For top-level navigational loads (e.g., form POST),
5565 // LoadingPrincipal is null. TriggeringPrincipal correctly represents the
5566 // origin that initiated the request in all cases. The old code using
5567 // LoadingPrincipal fell through to comparing mOriginalURI with mURI, which
5568 // are equal for the first redirect, incorrectly skipping the taint.
5569 if (StaticPrefs::network_http_origin_useTriggeringPrincipal()) {
5570 nsIPrincipal* triggeringPrincipal = mLoadInfo->TriggeringPrincipal();
5571 if (!triggeringPrincipal) {
5572 return true;
5573 }
5574 bool sameOrigin = false;
5575 nsresult rv = triggeringPrincipal->IsSameOrigin(mURI, &sameOrigin);
5576 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5577 return true;
5578 }
5579 return !sameOrigin;
5580 }
5581
5582 // Old code path (Bug 1965430): retained behind pref for safety.
5583 // Uses LoadingPrincipal which is null for top-level navigations,
5584 // falling back to mOriginalURI vs mURI comparison.
5585 nsresult rv;
5586 if (mLoadInfo->GetLoadingPrincipal()) {
5587 bool sameOrigin = false;
5588 rv = mLoadInfo->GetLoadingPrincipal()->IsSameOrigin(mURI, &sameOrigin);
5589 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5590 return true;
5591 }
5592 return !sameOrigin;
5593 }
5594 if (!mOriginalURI) {
5595 return true;
5596 }
5597
5598 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5599 if (!ssm) {
5600 return true;
5601 }
5602
5603 rv = ssm->CheckSameOriginURI(mOriginalURI, mURI, false, false);
5604 return NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)));
5605}
5606
5607// Redirect Tracking
5608bool HttpBaseChannel::SameOriginWithOriginalUri(nsIURI* aURI) {
5609 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5610 bool isPrivateWin = mLoadInfo->GetOriginAttributes().IsPrivateBrowsing();
5611 nsresult rv =
5612 ssm->CheckSameOriginURI(aURI, mOriginalURI, false, isPrivateWin);
5613 return (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))));
5614}
5615
5616//-----------------------------------------------------------------------------
5617// HttpBaseChannel::nsIClassifiedChannel
5618
5619NS_IMETHODIMPnsresult
5620HttpBaseChannel::GetMatchedList(nsACString& aList) {
5621 aList = mMatchedList;
5622 return NS_OK;
5623}
5624
5625NS_IMETHODIMPnsresult
5626HttpBaseChannel::GetMatchedProvider(nsACString& aProvider) {
5627 aProvider = mMatchedProvider;
5628 return NS_OK;
5629}
5630
5631NS_IMETHODIMPnsresult
5632HttpBaseChannel::GetMatchedFullHash(nsACString& aFullHash) {
5633 aFullHash = mMatchedFullHash;
5634 return NS_OK;
5635}
5636
5637NS_IMETHODIMPnsresult
5638HttpBaseChannel::SetMatchedInfo(const nsACString& aList,
5639 const nsACString& aProvider,
5640 const nsACString& aFullHash) {
5641 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"
, 5641); return NS_ERROR_INVALID_ARG; } } while (false)
;
5642
5643 mMatchedList = aList;
5644 mMatchedProvider = aProvider;
5645 mMatchedFullHash = aFullHash;
5646 return NS_OK;
5647}
5648
5649NS_IMETHODIMPnsresult
5650HttpBaseChannel::GetMatchedTrackingLists(nsTArray<nsCString>& aLists) {
5651 aLists = mMatchedTrackingLists.Clone();
5652 return NS_OK;
5653}
5654
5655NS_IMETHODIMPnsresult
5656HttpBaseChannel::GetMatchedTrackingFullHashes(
5657 nsTArray<nsCString>& aFullHashes) {
5658 aFullHashes = mMatchedTrackingFullHashes.Clone();
5659 return NS_OK;
5660}
5661
5662NS_IMETHODIMPnsresult
5663HttpBaseChannel::SetMatchedTrackingInfo(
5664 const nsTArray<nsCString>& aLists, const nsTArray<nsCString>& aFullHashes) {
5665 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"
, 5665); return NS_ERROR_INVALID_ARG; } } while (false)
;
5666 // aFullHashes can be empty for non hash-matching algorithm, for example,
5667 // host based test entries in preference.
5668
5669 mMatchedTrackingLists = aLists.Clone();
5670 mMatchedTrackingFullHashes = aFullHashes.Clone();
5671 return NS_OK;
5672}
5673//-----------------------------------------------------------------------------
5674// HttpBaseChannel::nsITimedChannel
5675//-----------------------------------------------------------------------------
5676
5677NS_IMETHODIMPnsresult
5678HttpBaseChannel::GetChannelCreation(TimeStamp* _retval) {
5679 *_retval = mChannelCreationTimestamp;
5680 return NS_OK;
5681}
5682
5683NS_IMETHODIMPnsresult
5684HttpBaseChannel::SetChannelCreation(TimeStamp aValue) {
5685 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", 5685
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aValue.IsNull()"
")"); do { MOZ_CrashSequence(__null, 5685); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5686 TimeDuration adjust = aValue - mChannelCreationTimestamp;
5687 mChannelCreationTimestamp = aValue;
5688 mChannelCreationTime += (PRTime)adjust.ToMicroseconds();
5689 return NS_OK;
5690}
5691
5692NS_IMETHODIMPnsresult
5693HttpBaseChannel::GetAsyncOpen(TimeStamp* _retval) {
5694 *_retval = mAsyncOpenTime;
5695 return NS_OK;
5696}
5697
5698NS_IMETHODIMPnsresult
5699HttpBaseChannel::SetAsyncOpen(TimeStamp aValue) {
5700 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", 5700
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aValue.IsNull()"
")"); do { MOZ_CrashSequence(__null, 5700); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5701 mAsyncOpenTime = aValue;
5702 StoreAsyncOpenTimeOverriden(true);
5703 return NS_OK;
5704}
5705
5706/**
5707 * @return the number of redirects. There is no check for cross-domain
5708 * redirects. This check must be done by the consumers.
5709 */
5710NS_IMETHODIMPnsresult
5711HttpBaseChannel::GetRedirectCount(uint8_t* aRedirectCount) {
5712 *aRedirectCount = mRedirectCount;
5713 return NS_OK;
5714}
5715
5716NS_IMETHODIMPnsresult
5717HttpBaseChannel::SetRedirectCount(uint8_t aRedirectCount) {
5718 mRedirectCount = aRedirectCount;
5719 return NS_OK;
5720}
5721
5722NS_IMETHODIMPnsresult
5723HttpBaseChannel::GetInternalRedirectCount(uint8_t* aRedirectCount) {
5724 *aRedirectCount = mInternalRedirectCount;
5725 return NS_OK;
5726}
5727
5728NS_IMETHODIMPnsresult
5729HttpBaseChannel::SetInternalRedirectCount(uint8_t aRedirectCount) {
5730 mInternalRedirectCount = aRedirectCount;
5731 return NS_OK;
5732}
5733
5734NS_IMETHODIMPnsresult
5735HttpBaseChannel::GetRedirectStart(TimeStamp* _retval) {
5736 *_retval = mRedirectStartTimeStamp;
5737 return NS_OK;
5738}
5739
5740NS_IMETHODIMPnsresult
5741HttpBaseChannel::SetRedirectStart(TimeStamp aRedirectStart) {
5742 mRedirectStartTimeStamp = aRedirectStart;
5743 return NS_OK;
5744}
5745
5746NS_IMETHODIMPnsresult
5747HttpBaseChannel::GetRedirectEnd(TimeStamp* _retval) {
5748 *_retval = mRedirectEndTimeStamp;
5749 return NS_OK;
5750}
5751
5752NS_IMETHODIMPnsresult
5753HttpBaseChannel::SetRedirectEnd(TimeStamp aRedirectEnd) {
5754 mRedirectEndTimeStamp = aRedirectEnd;
5755 return NS_OK;
5756}
5757
5758NS_IMETHODIMPnsresult
5759HttpBaseChannel::GetAllRedirectsSameOrigin(bool* aAllRedirectsSameOrigin) {
5760 *aAllRedirectsSameOrigin = LoadAllRedirectsSameOrigin();
5761 return NS_OK;
5762}
5763
5764NS_IMETHODIMPnsresult
5765HttpBaseChannel::SetAllRedirectsSameOrigin(bool aAllRedirectsSameOrigin) {
5766 StoreAllRedirectsSameOrigin(aAllRedirectsSameOrigin);
5767 return NS_OK;
5768}
5769
5770NS_IMETHODIMPnsresult
5771HttpBaseChannel::GetAllRedirectsSameOriginIgnoringInternal(
5772 bool* aAllRedirectsSameOriginIgnoringInternal) {
5773 *aAllRedirectsSameOriginIgnoringInternal =
5774 LoadAllRedirectsSameOriginIgnoringInternal();
5775 return NS_OK;
5776}
5777
5778NS_IMETHODIMPnsresult
5779HttpBaseChannel::SetAllRedirectsSameOriginIgnoringInternal(
5780 bool aAllRedirectsSameOriginIgnoringInternal) {
5781 StoreAllRedirectsSameOriginIgnoringInternal(
5782 aAllRedirectsSameOriginIgnoringInternal);
5783 return NS_OK;
5784}
5785
5786NS_IMETHODIMPnsresult
5787HttpBaseChannel::GetAllRedirectsPassTimingAllowCheck(bool* aPassesCheck) {
5788 *aPassesCheck = LoadAllRedirectsPassTimingAllowCheck();
5789 return NS_OK;
5790}
5791
5792NS_IMETHODIMPnsresult
5793HttpBaseChannel::SetAllRedirectsPassTimingAllowCheck(bool aPassesCheck) {
5794 StoreAllRedirectsPassTimingAllowCheck(aPassesCheck);
5795 return NS_OK;
5796}
5797
5798// https://fetch.spec.whatwg.org/#cors-check
5799bool HttpBaseChannel::PerformCORSCheck() {
5800 // Step 1
5801 // Let origin be the result of getting `Access-Control-Allow-Origin`
5802 // from response’s header list.
5803 nsAutoCString origin;
5804 nsresult rv = GetResponseHeader("Access-Control-Allow-Origin"_ns, origin);
5805
5806 // Step 2
5807 // If origin is null, then return failure. (Note: null, not 'null').
5808 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || origin.IsVoid()) {
5809 return false;
5810 }
5811
5812 // Step 3
5813 // If request’s credentials mode is not "include"
5814 // and origin is `*`, then return success.
5815 uint32_t cookiePolicy = mLoadInfo->GetCookiePolicy();
5816 if (cookiePolicy != nsILoadInfo::SEC_COOKIES_INCLUDE &&
5817 origin.EqualsLiteral("*")) {
5818 return true;
5819 }
5820
5821 // Step 4
5822 // If the result of byte-serializing a request origin
5823 // with request is not origin, then return failure.
5824 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5825 nsCOMPtr<nsIPrincipal> resourcePrincipal;
5826 rv = ssm->GetChannelURIPrincipal(this, getter_AddRefs(resourcePrincipal));
5827 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !resourcePrincipal) {
5828 return false;
5829 }
5830 nsAutoCString serializedOrigin;
5831 nsContentSecurityManager::GetSerializedOrigin(
5832 mLoadInfo->TriggeringPrincipal(), resourcePrincipal, serializedOrigin,
5833 mLoadInfo);
5834 if (!serializedOrigin.Equals(origin)) {
5835 return false;
5836 }
5837
5838 // Step 5
5839 // If request’s credentials mode is not "include", then return success.
5840 if (cookiePolicy != nsILoadInfo::SEC_COOKIES_INCLUDE) {
5841 return true;
5842 }
5843
5844 // Step 6
5845 // Let credentials be the result of getting
5846 // `Access-Control-Allow-Credentials` from response’s header list.
5847 nsAutoCString credentials;
5848 rv = GetResponseHeader("Access-Control-Allow-Credentials"_ns, credentials);
5849
5850 // Step 7 and 8
5851 // If credentials is `true`, then return success.
5852 // (else) return failure.
5853 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && credentials.EqualsLiteral("true");
5854}
5855
5856NS_IMETHODIMPnsresult
5857HttpBaseChannel::BodyInfoAccessAllowedCheck(nsIPrincipal* aOrigin,
5858 BodyInfoAccess* _retval) {
5859 // Per the Fetch spec, https://fetch.spec.whatwg.org/#response-body-info,
5860 // the bodyInfo for Resource Timing and Navigation Timing info consists of
5861 // encoded size, decoded size, and content type. It is however made opaque
5862 // whenever the response is turned into a network error, which sets its
5863 // bodyInfo to its default values (sizes=0, content-type="").
5864
5865 // Case 1:
5866 // "no-cors" -> Upon success, fetch will return an opaque filtered response.
5867 // An opaque(-redirect) filtered response is a filtered response
5868 // whose ... body info is a new response body info.
5869 auto tainting = mLoadInfo->GetTainting();
5870 if (tainting == mozilla::LoadTainting::Opaque) {
5871 *_retval = BodyInfoAccess::DISALLOWED;
5872 return NS_OK;
5873 }
5874
5875 // Case 2:
5876 // If request’s response tainting is "cors" and a CORS check for request
5877 // and response returns failure, then return a network error.
5878 if (tainting == mozilla::LoadTainting::CORS && !PerformCORSCheck()) {
5879 *_retval = BodyInfoAccess::DISALLOWED;
5880 return NS_OK;
5881 }
5882
5883 // Otherwise:
5884 // The fetch response handover, given a fetch params fetchParams
5885 // and a response response, run these steps:
5886 // processResponseEndOfBody:
5887 // - If fetchParams’s request’s mode is not "navigate" or response’s
5888 // has-cross-origin-redirects is false:
5889 // - Let mimeType be the result of extracting a MIME type from
5890 // response’s header list.
5891 // - If mimeType is not failure, then set bodyInfo’s content type to the
5892 // result of minimizing a supported MIME type given mimeType.
5893 dom::RequestMode requestMode;
5894 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", 5894
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(GetRequestMode(&requestMode))"
")"); do { MOZ_CrashSequence(__null, 5894); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
5895 if (requestMode != RequestMode::Navigate || LoadAllRedirectsSameOrigin()) {
5896 *_retval = BodyInfoAccess::ALLOW_ALL;
5897 return NS_OK;
5898 }
5899
5900 *_retval = BodyInfoAccess::ALLOW_SIZES;
5901 return NS_OK;
5902}
5903
5904// https://fetch.spec.whatwg.org/#tao-check
5905NS_IMETHODIMPnsresult
5906HttpBaseChannel::TimingAllowCheck(nsIPrincipal* aOrigin, bool* _retval) {
5907 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
5908 nsCOMPtr<nsIPrincipal> resourcePrincipal;
5909 nsresult rv =
5910 ssm->GetChannelURIPrincipal(this, getter_AddRefs(resourcePrincipal));
5911 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !resourcePrincipal || !aOrigin) {
5912 *_retval = false;
5913 return NS_OK;
5914 }
5915
5916 bool sameOrigin = false;
5917 rv = resourcePrincipal->Equals(aOrigin, &sameOrigin);
5918
5919 nsAutoCString serializedOrigin;
5920 nsContentSecurityManager::GetSerializedOrigin(aOrigin, resourcePrincipal,
5921 serializedOrigin, mLoadInfo);
5922
5923 // All redirects are same origin
5924 if (sameOrigin && (!serializedOrigin.IsEmpty() &&
5925 !serializedOrigin.EqualsLiteral("null"))) {
5926 *_retval = true;
5927 return NS_OK;
5928 }
5929
5930 nsAutoCString headerValue;
5931 rv = GetResponseHeader("Timing-Allow-Origin"_ns, headerValue);
5932 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5933 *_retval = false;
5934 return NS_OK;
5935 }
5936
5937 Tokenizer p(headerValue);
5938 Tokenizer::Token t;
5939
5940 p.Record();
5941 nsAutoCString headerItem;
5942 while (p.Next(t)) {
5943 if (t.Type() == Tokenizer::TOKEN_EOF ||
5944 t.Equals(Tokenizer::Token::Char(','))) {
5945 p.Claim(headerItem);
5946 nsHttp::TrimHTTPWhitespace(headerItem, headerItem);
5947 // If the list item contains a case-sensitive match for the value of the
5948 // origin, or a wildcard, return pass
5949 if (headerItem == serializedOrigin || headerItem == "*") {
5950 *_retval = true;
5951 return NS_OK;
5952 }
5953 // We start recording again for the following items in the list
5954 p.Record();
5955 }
5956 }
5957
5958 *_retval = false;
5959 return NS_OK;
5960}
5961
5962NS_IMETHODIMPnsresult
5963HttpBaseChannel::GetLaunchServiceWorkerStart(TimeStamp* _retval) {
5964 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"
, 5964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 5964); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5965 *_retval = mLaunchServiceWorkerStart;
5966 return NS_OK;
5967}
5968
5969NS_IMETHODIMPnsresult
5970HttpBaseChannel::SetLaunchServiceWorkerStart(TimeStamp aTimeStamp) {
5971 mLaunchServiceWorkerStart = aTimeStamp;
5972 return NS_OK;
5973}
5974
5975NS_IMETHODIMPnsresult
5976HttpBaseChannel::GetLaunchServiceWorkerEnd(TimeStamp* _retval) {
5977 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"
, 5977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 5977); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5978 *_retval = mLaunchServiceWorkerEnd;
5979 return NS_OK;
5980}
5981
5982NS_IMETHODIMPnsresult
5983HttpBaseChannel::SetLaunchServiceWorkerEnd(TimeStamp aTimeStamp) {
5984 mLaunchServiceWorkerEnd = aTimeStamp;
5985 return NS_OK;
5986}
5987
5988NS_IMETHODIMPnsresult
5989HttpBaseChannel::GetDispatchFetchEventStart(TimeStamp* _retval) {
5990 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"
, 5990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 5990); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5991 *_retval = mDispatchFetchEventStart;
5992 return NS_OK;
5993}
5994
5995NS_IMETHODIMPnsresult
5996HttpBaseChannel::SetDispatchFetchEventStart(TimeStamp aTimeStamp) {
5997 mDispatchFetchEventStart = aTimeStamp;
5998 return NS_OK;
5999}
6000
6001NS_IMETHODIMPnsresult
6002HttpBaseChannel::GetDispatchFetchEventEnd(TimeStamp* _retval) {
6003 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"
, 6003); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 6003); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6004 *_retval = mDispatchFetchEventEnd;
6005 return NS_OK;
6006}
6007
6008NS_IMETHODIMPnsresult
6009HttpBaseChannel::SetDispatchFetchEventEnd(TimeStamp aTimeStamp) {
6010 mDispatchFetchEventEnd = aTimeStamp;
6011 return NS_OK;
6012}
6013
6014NS_IMETHODIMPnsresult
6015HttpBaseChannel::GetHandleFetchEventStart(TimeStamp* _retval) {
6016 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"
, 6016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 6016); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6017 *_retval = mHandleFetchEventStart;
6018 return NS_OK;
6019}
6020
6021NS_IMETHODIMPnsresult
6022HttpBaseChannel::SetHandleFetchEventStart(TimeStamp aTimeStamp) {
6023 mHandleFetchEventStart = aTimeStamp;
6024 return NS_OK;
6025}
6026
6027NS_IMETHODIMPnsresult
6028HttpBaseChannel::GetHandleFetchEventEnd(TimeStamp* _retval) {
6029 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"
, 6029); AnnotateMozCrashReason("MOZ_ASSERT" "(" "_retval" ")"
); do { MOZ_CrashSequence(__null, 6029); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6030 *_retval = mHandleFetchEventEnd;
6031 return NS_OK;
6032}
6033
6034NS_IMETHODIMPnsresult
6035HttpBaseChannel::SetHandleFetchEventEnd(TimeStamp aTimeStamp) {
6036 mHandleFetchEventEnd = aTimeStamp;
6037 return NS_OK;
6038}
6039
6040NS_IMETHODIMPnsresult
6041HttpBaseChannel::GetDomainLookupStart(TimeStamp* _retval) {
6042 *_retval = mTransactionTimings.domainLookupStart;
6043 return NS_OK;
6044}
6045
6046NS_IMETHODIMPnsresult
6047HttpBaseChannel::GetDomainLookupEnd(TimeStamp* _retval) {
6048 *_retval = mTransactionTimings.domainLookupEnd;
6049 return NS_OK;
6050}
6051
6052NS_IMETHODIMPnsresult
6053HttpBaseChannel::GetConnectStart(TimeStamp* _retval) {
6054 *_retval = mTransactionTimings.connectStart;
6055 return NS_OK;
6056}
6057
6058NS_IMETHODIMPnsresult
6059HttpBaseChannel::GetTcpConnectEnd(TimeStamp* _retval) {
6060 *_retval = mTransactionTimings.tcpConnectEnd;
6061 return NS_OK;
6062}
6063
6064NS_IMETHODIMPnsresult
6065HttpBaseChannel::GetSecureConnectionStart(TimeStamp* _retval) {
6066 *_retval = mTransactionTimings.secureConnectionStart;
6067 return NS_OK;
6068}
6069
6070NS_IMETHODIMPnsresult
6071HttpBaseChannel::GetConnectEnd(TimeStamp* _retval) {
6072 *_retval = mTransactionTimings.connectEnd;
6073 return NS_OK;
6074}
6075
6076NS_IMETHODIMPnsresult
6077HttpBaseChannel::GetRequestStart(TimeStamp* _retval) {
6078 *_retval = mTransactionTimings.requestStart;
6079 return NS_OK;
6080}
6081
6082NS_IMETHODIMPnsresult
6083HttpBaseChannel::GetResponseStart(TimeStamp* _retval) {
6084 *_retval = mTransactionTimings.responseStart;
6085 return NS_OK;
6086}
6087
6088NS_IMETHODIMPnsresult
6089HttpBaseChannel::GetFirstInterimResponseStart(TimeStamp* _retval) {
6090 *_retval = mTransactionTimings.firstInterimResponseStart;
6091 return NS_OK;
6092}
6093
6094NS_IMETHODIMPnsresult
6095HttpBaseChannel::GetFinalResponseHeadersStart(TimeStamp* _retval) {
6096 *_retval = mTransactionTimings.finalResponseHeadersStart;
6097 return NS_OK;
6098}
6099
6100NS_IMETHODIMPnsresult
6101HttpBaseChannel::GetResponseEnd(TimeStamp* _retval) {
6102 *_retval = mTransactionTimings.responseEnd;
6103 return NS_OK;
6104}
6105
6106NS_IMETHODIMPnsresult
6107HttpBaseChannel::GetCacheReadStart(TimeStamp* _retval) {
6108 *_retval = mCacheReadStart;
6109 return NS_OK;
6110}
6111
6112NS_IMETHODIMPnsresult
6113HttpBaseChannel::GetCacheReadEnd(TimeStamp* _retval) {
6114 *_retval = mCacheReadEnd;
6115 return NS_OK;
6116}
6117
6118NS_IMETHODIMPnsresult
6119HttpBaseChannel::GetTransactionPending(TimeStamp* _retval) {
6120 *_retval = mTransactionTimings.transactionPending;
6121 return NS_OK;
6122}
6123
6124NS_IMETHODIMPnsresult
6125HttpBaseChannel::GetInitiatorType(nsAString& aInitiatorType) {
6126 aInitiatorType = mInitiatorType;
6127 return NS_OK;
6128}
6129
6130NS_IMETHODIMPnsresult
6131HttpBaseChannel::SetInitiatorType(const nsAString& aInitiatorType) {
6132 mInitiatorType = aInitiatorType;
6133 return NS_OK;
6134}
6135
6136#define IMPL_TIMING_ATTR(name) \
6137 NS_IMETHODIMPnsresult \
6138 HttpBaseChannel::Get##name##Time(PRTime* _retval) { \
6139 TimeStamp stamp; \
6140 Get##name(&stamp); \
6141 if (stamp.IsNull()) { \
6142 *_retval = 0; \
6143 return NS_OK; \
6144 } \
6145 *_retval = \
6146 mChannelCreationTime + \
6147 (PRTime)((stamp - mChannelCreationTimestamp).ToSeconds() * 1e6); \
6148 return NS_OK; \
6149 }
6150
6151IMPL_TIMING_ATTR(ChannelCreation)
6152IMPL_TIMING_ATTR(AsyncOpen)
6153IMPL_TIMING_ATTR(LaunchServiceWorkerStart)
6154IMPL_TIMING_ATTR(LaunchServiceWorkerEnd)
6155IMPL_TIMING_ATTR(DispatchFetchEventStart)
6156IMPL_TIMING_ATTR(DispatchFetchEventEnd)
6157IMPL_TIMING_ATTR(HandleFetchEventStart)
6158IMPL_TIMING_ATTR(HandleFetchEventEnd)
6159IMPL_TIMING_ATTR(DomainLookupStart)
6160IMPL_TIMING_ATTR(DomainLookupEnd)
6161IMPL_TIMING_ATTR(ConnectStart)
6162IMPL_TIMING_ATTR(TcpConnectEnd)
6163IMPL_TIMING_ATTR(SecureConnectionStart)
6164IMPL_TIMING_ATTR(ConnectEnd)
6165IMPL_TIMING_ATTR(RequestStart)
6166IMPL_TIMING_ATTR(ResponseStart)
6167IMPL_TIMING_ATTR(FirstInterimResponseStart)
6168IMPL_TIMING_ATTR(FinalResponseHeadersStart)
6169IMPL_TIMING_ATTR(ResponseEnd)
6170IMPL_TIMING_ATTR(CacheReadStart)
6171IMPL_TIMING_ATTR(CacheReadEnd)
6172IMPL_TIMING_ATTR(RedirectStart)
6173IMPL_TIMING_ATTR(RedirectEnd)
6174IMPL_TIMING_ATTR(TransactionPending)
6175
6176#undef IMPL_TIMING_ATTR
6177
6178void HttpBaseChannel::MaybeReportTimingDataForRedirect(
6179 nsISupports* aNewChannel) {
6180 nsCOMPtr<nsITimedChannel> newTimedChannel = do_QueryInterface(aNewChannel);
6181 if (!newTimedChannel) {
6182 MaybeReportTimingData();
6183 }
6184}
6185
6186void HttpBaseChannel::MaybeReportTimingData() {
6187 // There is no point in continuing, since the performance object in the parent
6188 // isn't the same as the one in the child which will be reporting resource
6189 // performance.
6190 if (XRE_IsE10sParentProcess()) {
6191 return;
6192 }
6193
6194 // Devtools can create fetch requests on behalf the content document.
6195 // If we don't exclude these requests, they'd also be reported
6196 // to the content document.
6197 bool isInDevToolsContext;
6198 mLoadInfo->GetIsInDevToolsContext(&isInDevToolsContext);
6199 if (isInDevToolsContext) {
6200 return;
6201 }
6202
6203 mozilla::dom::PerformanceStorage* documentPerformance =
6204 mLoadInfo->GetPerformanceStorage();
6205 if (documentPerformance) {
6206 documentPerformance->AddEntry(this, this);
6207 return;
6208 }
6209
6210 if (!nsGlobalWindowInner::GetInnerWindowWithId(
6211 mLoadInfo->GetInnerWindowID())) {
6212 // The inner window is in a different process.
6213 dom::ContentChild* child = dom::ContentChild::GetSingleton();
6214
6215 if (!child) {
6216 return;
6217 }
6218 nsAutoString initiatorType;
6219 nsAutoString entryName;
6220
6221 UniquePtr<dom::PerformanceTimingData> performanceTimingData(
6222 dom::PerformanceTimingData::Create(this, this, 0, initiatorType,
6223 entryName));
6224 if (!performanceTimingData) {
6225 return;
6226 }
6227
6228 LoadInfoArgs loadInfoArgs;
6229 mozilla::ipc::LoadInfoToLoadInfoArgs(mLoadInfo, &loadInfoArgs);
6230 child->SendReportFrameTimingData(loadInfoArgs, entryName, initiatorType,
6231 std::move(performanceTimingData));
6232 }
6233}
6234
6235NS_IMETHODIMPnsresult
6236HttpBaseChannel::SetReportResourceTiming(bool enabled) {
6237 StoreReportTiming(enabled);
6238 return NS_OK;
6239}
6240
6241NS_IMETHODIMPnsresult
6242HttpBaseChannel::GetReportResourceTiming(bool* _retval) {
6243 *_retval = LoadReportTiming();
6244 return NS_OK;
6245}
6246
6247nsIURI* HttpBaseChannel::GetReferringPage() {
6248 nsCOMPtr<nsPIDOMWindowInner> pDomWindow = GetInnerDOMWindow();
6249 if (!pDomWindow) {
6250 return nullptr;
6251 }
6252 return pDomWindow->GetDocumentURI();
6253}
6254
6255nsPIDOMWindowInner* HttpBaseChannel::GetInnerDOMWindow() {
6256 nsCOMPtr<nsILoadContext> loadContext;
6257 NS_QueryNotificationCallbacks(this, loadContext);
6258 if (!loadContext) {
6259 return nullptr;
6260 }
6261 nsCOMPtr<mozIDOMWindowProxy> domWindow;
6262 loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
6263 if (!domWindow) {
6264 return nullptr;
6265 }
6266 auto* pDomWindow = nsPIDOMWindowOuter::From(domWindow);
6267 if (!pDomWindow) {
6268 return nullptr;
6269 }
6270 nsCOMPtr<nsPIDOMWindowInner> innerWindow =
6271 pDomWindow->GetCurrentInnerWindow();
6272 if (!innerWindow) {
6273 return nullptr;
6274 }
6275
6276 return innerWindow;
6277}
6278
6279//-----------------------------------------------------------------------------
6280// HttpBaseChannel::nsIThrottledInputChannel
6281//-----------------------------------------------------------------------------
6282
6283NS_IMETHODIMPnsresult
6284HttpBaseChannel::SetThrottleQueue(nsIInputChannelThrottleQueue* aQueue) {
6285 if (!XRE_IsParentProcess()) {
6286 return NS_ERROR_FAILURE;
6287 }
6288
6289 mThrottleQueue = aQueue;
6290 return NS_OK;
6291}
6292
6293NS_IMETHODIMPnsresult
6294HttpBaseChannel::GetThrottleQueue(nsIInputChannelThrottleQueue** aQueue) {
6295 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", 6295
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
6296 nsCOMPtr<nsIInputChannelThrottleQueue> queue = mThrottleQueue;
6297 queue.forget(aQueue);
6298 return NS_OK;
6299}
6300
6301//------------------------------------------------------------------------------
6302
6303bool HttpBaseChannel::EnsureRequestContextID() {
6304 if (mRequestContextID) {
6305 // Already have a request context ID, no need to do the rest of this work
6306 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)
6307 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)
;
6308 return true;
6309 }
6310
6311 // Find the loadgroup at the end of the chain in order
6312 // to make sure all channels derived from the load group
6313 // use the same connection scope.
6314 if (!mLoadGroup) {
6315 return false;
6316 }
6317
6318 nsCOMPtr<nsILoadGroup> rootLoadGroup;
6319 mLoadGroup->GetRootLoadGroup(getter_AddRefs(rootLoadGroup));
6320 if (!rootLoadGroup) {
6321 return false;
6322 }
6323
6324 // Set the load group connection scope on this channel and its transaction
6325 rootLoadGroup->GetRequestContextID(&mRequestContextID);
6326
6327 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)
6328 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)
;
6329
6330 return true;
6331}
6332
6333bool HttpBaseChannel::EnsureRequestContext() {
6334 if (mRequestContext) {
6335 // Already have a request context, no need to do the rest of this work
6336 return true;
6337 }
6338
6339 if (!EnsureRequestContextID()) {
6340 return false;
6341 }
6342
6343 nsIRequestContextService* rcsvc = gHttpHandler->GetRequestContextService();
6344 if (!rcsvc) {
6345 return false;
6346 }
6347
6348 rcsvc->GetRequestContext(mRequestContextID, getter_AddRefs(mRequestContext));
6349 return static_cast<bool>(mRequestContext);
6350}
6351
6352void HttpBaseChannel::EnsureBrowserId() {
6353 if (mBrowserId) {
6354 return;
6355 }
6356
6357 RefPtr<dom::BrowsingContext> bc;
6358 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", 6358
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)))"
")"); do { MOZ_CrashSequence(__null, 6358); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
6359
6360 if (bc) {
6361 mBrowserId = bc->GetBrowserId();
6362 }
6363}
6364
6365void HttpBaseChannel::SetCorsPreflightParameters(
6366 const nsTArray<nsCString>& aUnsafeHeaders,
6367 bool aShouldStripRequestBodyHeader, bool aShouldStripAuthHeader) {
6368 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"
, 6368); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequestObserversCalled()"
")"); do { MOZ_CrashSequence(__null, 6368); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6369
6370 StoreRequireCORSPreflight(true);
6371 mUnsafeHeaders = aUnsafeHeaders.Clone();
6372 if (aShouldStripRequestBodyHeader || aShouldStripAuthHeader) {
6373 mUnsafeHeaders.RemoveElementsBy([&](const nsCString& aHeader) {
6374 return (aShouldStripRequestBodyHeader &&
6375 (aHeader.LowerCaseEqualsASCII("content-type") ||
6376 aHeader.LowerCaseEqualsASCII("content-encoding") ||
6377 aHeader.LowerCaseEqualsASCII("content-language") ||
6378 aHeader.LowerCaseEqualsASCII("content-location"))) ||
6379 (aShouldStripAuthHeader &&
6380 aHeader.LowerCaseEqualsASCII("authorization"));
6381 });
6382 }
6383}
6384
6385void HttpBaseChannel::SetAltDataForChild(bool aIsForChild) {
6386 StoreAltDataForChild(aIsForChild);
6387}
6388
6389NS_IMETHODIMPnsresult
6390HttpBaseChannel::GetBlockAuthPrompt(bool* aValue) {
6391 if (!aValue) {
6392 return NS_ERROR_FAILURE;
6393 }
6394
6395 *aValue = LoadBlockAuthPrompt();
6396 return NS_OK;
6397}
6398
6399NS_IMETHODIMPnsresult
6400HttpBaseChannel::SetBlockAuthPrompt(bool aValue) {
6401 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/HttpBaseChannel.cpp"
, 6401); 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"
, 6401, 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"
, 6401); } } 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", 6401
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 6401); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
6402
6403 StoreBlockAuthPrompt(aValue);
6404 return NS_OK;
6405}
6406
6407NS_IMETHODIMPnsresult
6408HttpBaseChannel::GetConnectionInfoHashKey(nsACString& aConnectionInfoHashKey) {
6409 if (!mConnectionInfo) {
6410 return NS_ERROR_FAILURE;
6411 }
6412 aConnectionInfoHashKey.Assign(mConnectionInfo->HashKey());
6413 return NS_OK;
6414}
6415
6416NS_IMETHODIMPnsresult
6417HttpBaseChannel::GetLastRedirectFlags(uint32_t* aValue) {
6418 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", 6418
); return NS_ERROR_INVALID_ARG; } } while (false)
;
6419 *aValue = mLastRedirectFlags;
6420 return NS_OK;
6421}
6422
6423NS_IMETHODIMPnsresult
6424HttpBaseChannel::SetLastRedirectFlags(uint32_t aValue) {
6425 mLastRedirectFlags = aValue;
6426 return NS_OK;
6427}
6428
6429NS_IMETHODIMPnsresult
6430HttpBaseChannel::GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) {
6431 return NS_ERROR_NOT_IMPLEMENTED;
6432}
6433
6434NS_IMETHODIMPnsresult
6435HttpBaseChannel::SetNavigationStartTimeStamp(TimeStamp aTimeStamp) {
6436 return NS_ERROR_NOT_IMPLEMENTED;
6437}
6438
6439nsresult HttpBaseChannel::CheckRedirectLimit(nsIURI* aNewURI,
6440 uint32_t aRedirectFlags) const {
6441 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
6442 // for internal redirect due to auth retry we do not have any limit
6443 // as we might restrict the number of times a user might retry
6444 // authentication
6445 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_AUTH_RETRY) {
6446 return NS_OK;
6447 }
6448 // Some platform features, like Service Workers, depend on internal
6449 // redirects. We should allow some number of internal redirects above
6450 // and beyond the normal redirect limit so these features continue
6451 // to work.
6452 static const int8_t kMinInternalRedirects = 5;
6453
6454 if (mInternalRedirectCount >= (mRedirectionLimit + kMinInternalRedirects)) {
6455 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)
;
6456 return NS_ERROR_REDIRECT_LOOP;
6457 }
6458 return NS_OK;
6459 }
6460
6461 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", 6463
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink::REDIRECT_STS_UPGRADE)"
")"); do { MOZ_CrashSequence(__null, 6463); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6462 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", 6463
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink::REDIRECT_STS_UPGRADE)"
")"); do { MOZ_CrashSequence(__null, 6463); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6463 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", 6463
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRedirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY | nsIChannelEventSink::REDIRECT_PERMANENT | nsIChannelEventSink::REDIRECT_STS_UPGRADE)"
")"); do { MOZ_CrashSequence(__null, 6463); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6464
6465 if (mRedirectCount >= mRedirectionLimit) {
6466 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)
;
6467 return NS_ERROR_REDIRECT_LOOP;
6468 }
6469
6470 // in case https-only mode is enabled which upgrades top-level requests to
6471 // https and the page answers with a redirect (meta, 302, win.location, ...)
6472 // then this method can break the cycle which causes the https-only exception
6473 // page to appear. Note that https-first mode breaks upgrade downgrade endless
6474 // loops within ShouldUpgradeHttpsFirstRequest because https-first does not
6475 // display an exception page but needs a soft fallback/downgrade.
6476 if (nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
6477 mURI, aNewURI, mLoadInfo,
6478 {nsHTTPSOnlyUtils::UpgradeDowngradeEndlessLoopOptions::
6479 EnforceForHTTPSOnlyMode})) {
6480 // Mark that we didn't upgrade to https due to loop detection in https-only
6481 // mode to show https-only error page. We know that we are in https-only
6482 // mode, because we passed `EnforceForHTTPSOnlyMode` to
6483 // `IsUpgradeDowngradeEndlessLoop`. In other words we upgrade the request
6484 // with https-only mode, but then immediately cancel the request.
6485 uint32_t httpsOnlyStatus = mLoadInfo->GetHttpsOnlyStatus();
6486 if (httpsOnlyStatus & nsILoadInfo::HTTPS_ONLY_UNINITIALIZED) {
6487 httpsOnlyStatus ^= nsILoadInfo::HTTPS_ONLY_UNINITIALIZED;
6488 httpsOnlyStatus |=
6489 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED;
6490 mLoadInfo->SetHttpsOnlyStatus(httpsOnlyStatus);
6491 }
6492
6493 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)
;
6494 return NS_ERROR_REDIRECT_LOOP;
6495 }
6496 // in case of http-first mode we want to add an exception to disable the
6497 // upgrade behavior if we have upgrade-downgrade loop to break the loop and
6498 // load the http request next
6499 if (mozilla::StaticPrefs::
6500 dom_security_https_first_add_exception_on_failure() &&
6501 nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
6502 mURI, aNewURI, mLoadInfo,
6503 {nsHTTPSOnlyUtils::UpgradeDowngradeEndlessLoopOptions::
6504 EnforceForHTTPSFirstMode})) {
6505 nsHTTPSOnlyUtils::AddHTTPSFirstException(mURI, mLoadInfo);
6506 }
6507
6508 return NS_OK;
6509}
6510
6511// NOTE: This function duplicates code from nsBaseChannel. This will go away
6512// once HTTP uses nsBaseChannel (part of bug 312760)
6513/* static */
6514void HttpBaseChannel::CallTypeSniffers(void* aClosure, const uint8_t* aData,
6515 uint32_t aCount) {
6516 nsIChannel* chan = static_cast<nsIChannel*>(aClosure);
6517 const char* snifferType = [chan]() {
6518 if (RefPtr<nsHttpChannel> httpChannel = do_QueryObject(chan)) {
6519 switch (httpChannel->GetSnifferCategoryType()) {
6520 case SnifferCategoryType::NetContent:
6521 return NS_CONTENT_SNIFFER_CATEGORY"net-content-sniffers";
6522 case SnifferCategoryType::OpaqueResponseBlocking:
6523 return NS_ORB_SNIFFER_CATEGORY"orb-content-sniffers";
6524 case SnifferCategoryType::All:
6525 return NS_CONTENT_AND_ORB_SNIFFER_CATEGORY"net-and-orb-content-sniffers";
6526 default:
6527 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"
, 6527); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected SnifferCategoryType!"
")"); do { MOZ_CrashSequence(__null, 6527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6528 }
6529 }
6530
6531 return NS_CONTENT_SNIFFER_CATEGORY"net-content-sniffers";
6532 }();
6533
6534 nsAutoCString newType;
6535 NS_SniffContent(snifferType, chan, aData, aCount, newType);
6536 if (!newType.IsEmpty()) {
6537 chan->SetContentType(newType);
6538 }
6539}
6540
6541template <class T>
6542static void ParseServerTimingHeader(
6543 const UniquePtr<T>& aHeader, nsTArray<nsCOMPtr<nsIServerTiming>>& aOutput) {
6544 if (!aHeader) {
6545 return;
6546 }
6547
6548 nsAutoCString serverTimingHeader;
6549 (void)aHeader->GetHeader(nsHttp::Server_Timing, serverTimingHeader);
6550 if (serverTimingHeader.IsEmpty()) {
6551 return;
6552 }
6553
6554 ServerTimingParser parser(serverTimingHeader);
6555 parser.Parse();
6556
6557 nsTArray<nsCOMPtr<nsIServerTiming>> array = parser.TakeServerTimingHeaders();
6558 aOutput.AppendElements(array);
6559}
6560
6561NS_IMETHODIMPnsresult
6562HttpBaseChannel::GetServerTiming(nsIArray** aServerTiming) {
6563 nsresult rv;
6564 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"
, 6564); return NS_ERROR_INVALID_POINTER; } } while (false)
;
6565
6566 nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID"@mozilla.org/array;1", &rv);
6567 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"
, 6567); return rv; } } while (false)
;
6568
6569 nsTArray<nsCOMPtr<nsIServerTiming>> data;
6570 rv = GetNativeServerTiming(data);
6571 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"
, 6571); return rv; } } while (false)
;
6572
6573 for (const auto& entry : data) {
6574 array->AppendElement(entry);
6575 }
6576
6577 array.forget(aServerTiming);
6578 return NS_OK;
6579}
6580
6581NS_IMETHODIMPnsresult
6582HttpBaseChannel::GetNativeServerTiming(
6583 nsTArray<nsCOMPtr<nsIServerTiming>>& aServerTiming) {
6584 aServerTiming.Clear();
6585
6586 if (nsContentUtils::ComputeIsSecureContext(this)) {
6587 ParseServerTimingHeader(mResponseHead, aServerTiming);
6588 ParseServerTimingHeader(mResponseTrailers, aServerTiming);
6589 }
6590
6591 return NS_OK;
6592}
6593
6594NS_IMETHODIMPnsresult
6595HttpBaseChannel::CancelByURLClassifier(nsresult aErrorCode) {
6596 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", 6596
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 6596); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6597 return Cancel(aErrorCode);
6598}
6599
6600NS_IMETHODIMPnsresult HttpBaseChannel::SetIPv4Disabled() {
6601 mCaps |= NS_HTTP_DISABLE_IPV4(1 << 17);
6602 return NS_OK;
6603}
6604
6605NS_IMETHODIMPnsresult HttpBaseChannel::SetIPv6Disabled() {
6606 mCaps |= NS_HTTP_DISABLE_IPV6(1 << 18);
6607 return NS_OK;
6608}
6609
6610NS_IMETHODIMPnsresult HttpBaseChannel::GetResponseEmbedderPolicy(
6611 bool aIsOriginTrialCoepCredentiallessEnabled,
6612 nsILoadInfo::CrossOriginEmbedderPolicy* aOutPolicy) {
6613 *aOutPolicy = nsILoadInfo::EMBEDDER_POLICY_NULL;
6614 if (!mResponseHead) {
6615 return NS_ERROR_NOT_AVAILABLE;
6616 }
6617
6618 if (!nsContentUtils::ComputeIsSecureContext(this)) {
6619 // Feature is only available for secure contexts.
6620 return NS_OK;
6621 }
6622
6623 nsAutoCString content;
6624 (void)mResponseHead->GetHeader(nsHttp::Cross_Origin_Embedder_Policy, content);
6625 *aOutPolicy = NS_GetCrossOriginEmbedderPolicyFromHeader(
6626 content, aIsOriginTrialCoepCredentiallessEnabled);
6627 return NS_OK;
6628}
6629
6630// Obtain a cross-origin opener-policy from a response response and a
6631// cross-origin opener policy initiator.
6632// https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
6633NS_IMETHODIMPnsresult HttpBaseChannel::ComputeCrossOriginOpenerPolicy(
6634 nsILoadInfo::CrossOriginOpenerPolicy aInitiatorPolicy,
6635 nsILoadInfo::CrossOriginOpenerPolicy* aOutPolicy) {
6636 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"
, 6636); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutPolicy"
")"); do { MOZ_CrashSequence(__null, 6636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6637 *aOutPolicy = nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
6638
6639 if (!mResponseHead) {
6640 return NS_ERROR_NOT_AVAILABLE;
6641 }
6642
6643 // COOP headers are ignored for insecure-context loads.
6644 if (!nsContentUtils::ComputeIsSecureContext(this)) {
6645 return NS_OK;
6646 }
6647
6648 nsAutoCString openerPolicy;
6649 (void)mResponseHead->GetHeader(nsHttp::Cross_Origin_Opener_Policy,
6650 openerPolicy);
6651
6652 // Cross-Origin-Opener-Policy = %s"same-origin" /
6653 // %s"same-origin-allow-popups" /
6654 // %s"unsafe-none"; case-sensitive
6655
6656 nsresult rv = SFV::ParseItem<SFV::Token>(openerPolicy, openerPolicy);
6657 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6658 return rv;
6659 }
6660
6661 nsILoadInfo::CrossOriginOpenerPolicy policy =
6662 nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
6663
6664 if (openerPolicy.EqualsLiteral("same-origin")) {
6665 policy = nsILoadInfo::OPENER_POLICY_SAME_ORIGIN;
6666 } else if (openerPolicy.EqualsLiteral("same-origin-allow-popups")) {
6667 policy = nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_ALLOW_POPUPS;
6668 }
6669 if (policy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN) {
6670 nsILoadInfo::CrossOriginEmbedderPolicy coep =
6671 nsILoadInfo::EMBEDDER_POLICY_NULL;
6672 bool isCoepCredentiallessEnabled;
6673 rv = mLoadInfo->GetIsOriginTrialCoepCredentiallessEnabledForTopLevel(
6674 &isCoepCredentiallessEnabled);
6675 if (!isCoepCredentiallessEnabled) {
6676 nsAutoCString originTrialToken;
6677 (void)mResponseHead->GetHeader(nsHttp::OriginTrial, originTrialToken);
6678 if (!originTrialToken.IsEmpty()) {
6679 nsCOMPtr<nsIPrincipal> resultPrincipal;
6680 rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
6681 this, getter_AddRefs(resultPrincipal));
6682 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"
, 6682)
) {
6683 OriginTrials trials;
6684 trials.UpdateFromToken(NS_ConvertASCIItoUTF16(originTrialToken),
6685 resultPrincipal);
6686 if (trials.IsEnabled(OriginTrial::CoepCredentialless)) {
6687 isCoepCredentiallessEnabled = true;
6688 }
6689 }
6690 }
6691 }
6692
6693 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"
, 6693); return rv; } } while (false)
;
6694 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetResponseEmbedderPolicy
(isCoepCredentiallessEnabled, &coep))), 1)))
6695 GetResponseEmbedderPolicy(isCoepCredentiallessEnabled, &coep))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetResponseEmbedderPolicy
(isCoepCredentiallessEnabled, &coep))), 1)))
&&
6696 (coep == nsILoadInfo::EMBEDDER_POLICY_REQUIRE_CORP ||
6697 coep == nsILoadInfo::EMBEDDER_POLICY_CREDENTIALLESS)) {
6698 policy =
6699 nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP;
6700 }
6701 }
6702
6703 *aOutPolicy = policy;
6704 return NS_OK;
6705}
6706
6707NS_IMETHODIMPnsresult
6708HttpBaseChannel::GetCrossOriginOpenerPolicy(
6709 nsILoadInfo::CrossOriginOpenerPolicy* aPolicy) {
6710 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"
, 6710); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPolicy" ")"
); do { MOZ_CrashSequence(__null, 6710); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6711 if (!aPolicy) {
6712 return NS_ERROR_INVALID_ARG;
6713 }
6714 // If this method is called before OnStartRequest (ie. before we call
6715 // ComputeCrossOriginOpenerPolicy) or if we were unable to compute the
6716 // policy we'll throw an error.
6717 if (!LoadOnStartRequestCalled()) {
6718 return NS_ERROR_NOT_AVAILABLE;
6719 }
6720 *aPolicy = mComputedCrossOriginOpenerPolicy;
6721 return NS_OK;
6722}
6723
6724NS_IMETHODIMPnsresult
6725HttpBaseChannel::HasCrossOriginOpenerPolicyMismatch(bool* aIsMismatch) {
6726 // This should only be called in parent process.
6727 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", 6727
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 6727); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6728 *aIsMismatch = LoadHasCrossOriginOpenerPolicyMismatch();
6729 return NS_OK;
6730}
6731
6732NS_IMETHODIMPnsresult
6733HttpBaseChannel::GetOriginAgentClusterHeader(bool* aValue) {
6734 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", 6734
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 6734); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6735 if (!mResponseHead) {
6736 return NS_ERROR_NOT_AVAILABLE;
6737 }
6738
6739 nsAutoCString content;
6740 nsresult rv = mResponseHead->GetHeader(nsHttp::OriginAgentCluster, content);
6741 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6742 return rv;
6743 }
6744
6745 // Origin-Agent-Cluster = <boolean>
6746 return SFV::ParseItem<SFV::SFVBool>(content, *aValue);
6747}
6748
6749void HttpBaseChannel::MaybeFlushConsoleReports() {
6750 // Flush if we have a known window ID.
6751 if (mLoadInfo->GetInnerWindowID() > 0) {
6752 FlushReportsToConsole(mLoadInfo->GetInnerWindowID());
6753 return;
6754 }
6755
6756 // If this channel is part of a loadGroup, we can flush the console reports
6757 // immediately.
6758 nsCOMPtr<nsILoadGroup> loadGroup;
6759 nsresult rv = GetLoadGroup(getter_AddRefs(loadGroup));
6760 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && loadGroup) {
6761 FlushConsoleReports(loadGroup);
6762 }
6763}
6764
6765void HttpBaseChannel::DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() {}
6766
6767bool HttpBaseChannel::Http3Allowed() const {
6768 bool allowedProxyInfo =
6769 mProxyInfo ? (static_cast<nsProxyInfo*>(mProxyInfo.get())->IsDirect() ||
6770 static_cast<nsProxyInfo*>(mProxyInfo.get())->IsHttp3Proxy())
6771 : true;
6772 // TODO: When mUpgradeProtocolCallback is not null, we should allow HTTP/3 for
6773 // connect-udp.
6774 return !mUpgradeProtocolCallback && allowedProxyInfo &&
6775 !(mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) && !LoadBeConservative() &&
6776 LoadAllowHttp3();
6777}
6778
6779UniquePtr<nsHttpResponseHead>
6780HttpBaseChannel::MaybeCloneResponseHeadForCachedResource() {
6781 if (!mResponseHead) {
6782 return nullptr;
6783 }
6784
6785 return MakeUnique<nsHttpResponseHead>(*mResponseHead);
6786}
6787
6788void HttpBaseChannel::SetDummyChannelForCachedResource(
6789 const nsHttpResponseHead* aMaybeResponseHead /* = nullptr */) {
6790 mDummyChannelForCachedResource = true;
6791 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"
, 6792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mResponseHead"
") (" "SetDummyChannelForCachedResource should only be called once"
")"); do { MOZ_CrashSequence(__null, 6792); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6792 "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"
, 6792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mResponseHead"
") (" "SetDummyChannelForCachedResource should only be called once"
")"); do { MOZ_CrashSequence(__null, 6792); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6793 if (aMaybeResponseHead) {
6794 mResponseHead = MakeUnique<nsHttpResponseHead>(*aMaybeResponseHead);
6795 } else {
6796 mResponseHead = MakeUnique<nsHttpResponseHead>();
6797 }
6798}
6799
6800void HttpBaseChannel::SetEarlyHints(
6801 nsTArray<EarlyHintConnectArgs>&& aEarlyHints) {
6802 mEarlyHints = std::move(aEarlyHints);
6803}
6804
6805nsTArray<EarlyHintConnectArgs>&& HttpBaseChannel::TakeEarlyHints() {
6806 return std::move(mEarlyHints);
6807}
6808
6809NS_IMETHODIMPnsresult
6810HttpBaseChannel::SetEarlyHintPreloaderId(uint64_t aEarlyHintPreloaderId) {
6811 mEarlyHintPreloaderId = aEarlyHintPreloaderId;
6812 return NS_OK;
6813}
6814
6815NS_IMETHODIMPnsresult
6816HttpBaseChannel::GetEarlyHintPreloaderId(uint64_t* aEarlyHintPreloaderId) {
6817 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"
, 6817); return NS_ERROR_INVALID_POINTER; } } while (false)
;
6818 *aEarlyHintPreloaderId = mEarlyHintPreloaderId;
6819 return NS_OK;
6820}
6821
6822NS_IMETHODIMPnsresult
6823HttpBaseChannel::SetClassicScriptHintCharset(
6824 const nsAString& aClassicScriptHintCharset) {
6825 mClassicScriptHintCharset = aClassicScriptHintCharset;
6826 return NS_OK;
6827}
6828
6829NS_IMETHODIMPnsresult HttpBaseChannel::GetClassicScriptHintCharset(
6830 nsAString& aClassicScriptHintCharset) {
6831 aClassicScriptHintCharset = mClassicScriptHintCharset;
6832 return NS_OK;
6833}
6834
6835NS_IMETHODIMPnsresult HttpBaseChannel::SetDocumentCharacterSet(
6836 const nsAString& aDocumentCharacterSet) {
6837 mDocumentCharacterSet = aDocumentCharacterSet;
6838 return NS_OK;
6839}
6840
6841NS_IMETHODIMPnsresult HttpBaseChannel::GetDocumentCharacterSet(
6842 nsAString& aDocumentCharacterSet) {
6843 aDocumentCharacterSet = mDocumentCharacterSet;
6844 return NS_OK;
6845}
6846
6847void HttpBaseChannel::SetConnectionInfo(nsHttpConnectionInfo* aCI) {
6848 mConnectionInfo = aCI;
6849}
6850
6851NS_IMETHODIMPnsresult
6852HttpBaseChannel::GetIsProxyUsed(bool* aIsProxyUsed) {
6853 if (mProxyInfo) {
6854 if (!static_cast<nsProxyInfo*>(mProxyInfo.get())->IsDirect()) {
6855 StoreIsProxyUsed(true);
6856 }
6857 }
6858 *aIsProxyUsed = LoadIsProxyUsed();
6859 return NS_OK;
6860}
6861
6862static void CollectORBBlockTelemetry(
6863 const OpaqueResponseBlockedTelemetryReason aTelemetryReason,
6864 ExtContentPolicy aPolicy) {
6865 glean::orb::block_reason.EnumGet(aTelemetryReason).Add();
6866
6867 switch (aPolicy) {
6868 case ExtContentPolicy::TYPE_INVALID:
6869 glean::orb::block_initiator
6870 .EnumGet(glean::orb::BlockInitiatorLabel::eInvalid)
6871 .Add();
6872 break;
6873 case ExtContentPolicy::TYPE_OTHER:
6874 glean::orb::block_initiator
6875 .EnumGet(glean::orb::BlockInitiatorLabel::eOther)
6876 .Add();
6877 break;
6878 case ExtContentPolicy::TYPE_FETCH:
6879 glean::orb::block_initiator
6880 .EnumGet(glean::orb::BlockInitiatorLabel::eBlockedFetch)
6881 .Add();
6882 break;
6883 case ExtContentPolicy::TYPE_SCRIPT:
6884 glean::orb::block_initiator
6885 .EnumGet(glean::orb::BlockInitiatorLabel::eScript)
6886 .Add();
6887 break;
6888 case ExtContentPolicy::TYPE_JSON:
6889 glean::orb::block_initiator
6890 .EnumGet(glean::orb::BlockInitiatorLabel::eJson)
6891 .Add();
6892 break;
6893 case ExtContentPolicy::TYPE_IMAGE:
6894 glean::orb::block_initiator
6895 .EnumGet(glean::orb::BlockInitiatorLabel::eImage)
6896 .Add();
6897 break;
6898 case ExtContentPolicy::TYPE_STYLESHEET:
6899 glean::orb::block_initiator
6900 .EnumGet(glean::orb::BlockInitiatorLabel::eStylesheet)
6901 .Add();
6902 break;
6903 case ExtContentPolicy::TYPE_XMLHTTPREQUEST:
6904 glean::orb::block_initiator
6905 .EnumGet(glean::orb::BlockInitiatorLabel::eXmlhttprequest)
6906 .Add();
6907 break;
6908 case ExtContentPolicy::TYPE_DTD:
6909 glean::orb::block_initiator.EnumGet(glean::orb::BlockInitiatorLabel::eDtd)
6910 .Add();
6911 break;
6912 case ExtContentPolicy::TYPE_FONT:
6913 glean::orb::block_initiator
6914 .EnumGet(glean::orb::BlockInitiatorLabel::eFont)
6915 .Add();
6916 break;
6917 case ExtContentPolicy::TYPE_MEDIA:
6918 glean::orb::block_initiator
6919 .EnumGet(glean::orb::BlockInitiatorLabel::eMedia)
6920 .Add();
6921 break;
6922 case ExtContentPolicy::TYPE_CSP_REPORT:
6923 glean::orb::block_initiator
6924 .EnumGet(glean::orb::BlockInitiatorLabel::eCspReport)
6925 .Add();
6926 break;
6927 case ExtContentPolicy::TYPE_XSLT:
6928 glean::orb::block_initiator
6929 .EnumGet(glean::orb::BlockInitiatorLabel::eXslt)
6930 .Add();
6931 break;
6932 case ExtContentPolicy::TYPE_IMAGESET:
6933 glean::orb::block_initiator
6934 .EnumGet(glean::orb::BlockInitiatorLabel::eImageset)
6935 .Add();
6936 break;
6937 case ExtContentPolicy::TYPE_WEB_MANIFEST:
6938 glean::orb::block_initiator
6939 .EnumGet(glean::orb::BlockInitiatorLabel::eWebManifest)
6940 .Add();
6941 break;
6942 case ExtContentPolicy::TYPE_SPECULATIVE:
6943 glean::orb::block_initiator
6944 .EnumGet(glean::orb::BlockInitiatorLabel::eSpeculative)
6945 .Add();
6946 break;
6947 case ExtContentPolicy::TYPE_UA_FONT:
6948 glean::orb::block_initiator
6949 .EnumGet(glean::orb::BlockInitiatorLabel::eUaFont)
6950 .Add();
6951 break;
6952 case ExtContentPolicy::TYPE_PROXIED_WEBRTC_MEDIA:
6953 glean::orb::block_initiator
6954 .EnumGet(glean::orb::BlockInitiatorLabel::eProxiedWebrtcMedia)
6955 .Add();
6956 break;
6957 case ExtContentPolicy::TYPE_PING:
6958 glean::orb::block_initiator
6959 .EnumGet(glean::orb::BlockInitiatorLabel::ePing)
6960 .Add();
6961 break;
6962 case ExtContentPolicy::TYPE_BEACON:
6963 glean::orb::block_initiator
6964 .EnumGet(glean::orb::BlockInitiatorLabel::eBeacon)
6965 .Add();
6966 break;
6967 case ExtContentPolicy::TYPE_WEB_TRANSPORT:
6968 glean::orb::block_initiator
6969 .EnumGet(glean::orb::BlockInitiatorLabel::eWebTransport)
6970 .Add();
6971 break;
6972 case ExtContentPolicy::TYPE_WEB_IDENTITY:
6973 // Don't bother extending the telemetry for this.
6974 glean::orb::block_initiator
6975 .EnumGet(glean::orb::BlockInitiatorLabel::eOther)
6976 .Add();
6977 break;
6978 case ExtContentPolicy::TYPE_TEXT:
6979 glean::orb::block_initiator
6980 .EnumGet(glean::orb::BlockInitiatorLabel::eText)
6981 .Add();
6982 break;
6983 case ExtContentPolicy::TYPE_DOCUMENT:
6984 case ExtContentPolicy::TYPE_SUBDOCUMENT:
6985 case ExtContentPolicy::TYPE_OBJECT:
6986 case ExtContentPolicy::TYPE_WEBSOCKET:
6987 case ExtContentPolicy::TYPE_SAVEAS_DOWNLOAD:
6988 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"
, 6988); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Shouldn't block this type" ")");
do { MOZ_CrashSequence(__null, 6988); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6989 // DOCUMENT, SUBDOCUMENT, OBJECT,
6990 // WEBSOCKET and SAVEAS_DOWNLOAD are excluded from ORB
6991 glean::orb::block_initiator
6992 .EnumGet(glean::orb::BlockInitiatorLabel::eExcluded)
6993 .Add();
6994 break;
6995 // Do not add default: so that compilers can catch the missing case.
6996 }
6997}
6998
6999void HttpBaseChannel::LogORBError(
7000 const nsAString& aReason,
7001 const OpaqueResponseBlockedTelemetryReason aTelemetryReason) {
7002 auto policy = mLoadInfo->GetExternalContentPolicyType();
7003 CollectORBBlockTelemetry(aTelemetryReason, policy);
7004
7005 // Blocking `ExtContentPolicy::TYPE_BEACON` isn't web observable, so keep
7006 // quiet in the console about blocking it.
7007 if (policy == ExtContentPolicy::TYPE_BEACON) {
7008 return;
7009 }
7010
7011 RefPtr<dom::Document> doc;
7012 mLoadInfo->GetLoadingDocument(getter_AddRefs(doc));
7013
7014 nsAutoCString uri;
7015 if (mURI->SchemeIs("data")) {
7016 uri.AssignLiteral("data:...");
7017 } else {
7018 nsCOMPtr<nsIURI> exposableURI = net::nsIOService::CreateExposableURI(mURI);
7019 exposableURI->GetSpec(uri);
7020 }
7021
7022 uint64_t contentWindowId;
7023 GetTopLevelContentWindowId(&contentWindowId);
7024 if (contentWindowId) {
7025 nsContentUtils::ReportToConsoleByWindowID(
7026 u"A resource is blocked by OpaqueResponseBlocking, please check browser console for details."_ns,
7027 nsIScriptError::warningFlag, "ORB"_ns, contentWindowId,
7028 SourceLocation(mURI.get()));
7029 }
7030
7031 AutoTArray<nsString, 2> params;
7032 params.AppendElement(NS_ConvertUTF8toUTF16(uri));
7033 params.AppendElement(aReason);
7034 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "ORB"_ns, doc,
7035 PropertiesFile::NECKO_PROPERTIES,
7036 "ResourceBlockedORB", params);
7037}
7038
7039NS_IMETHODIMPnsresult HttpBaseChannel::SetEarlyHintLinkType(
7040 uint32_t aEarlyHintLinkType) {
7041 mEarlyHintLinkType = aEarlyHintLinkType;
7042 return NS_OK;
7043}
7044
7045NS_IMETHODIMPnsresult HttpBaseChannel::GetEarlyHintLinkType(
7046 uint32_t* aEarlyHintLinkType) {
7047 *aEarlyHintLinkType = mEarlyHintLinkType;
7048 return NS_OK;
7049}
7050
7051NS_IMETHODIMPnsresult
7052HttpBaseChannel::SetHasContentDecompressed(bool aValue) {
7053 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)
7054 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)
;
7055 mHasContentDecompressed = aValue;
7056 return NS_OK;
7057}
7058NS_IMETHODIMPnsresult
7059HttpBaseChannel::GetHasContentDecompressed(bool* value) {
7060 *value = mHasContentDecompressed;
7061 return NS_OK;
7062}
7063
7064NS_IMETHODIMPnsresult
7065HttpBaseChannel::SetRenderBlocking(bool aRenderBlocking) {
7066 mRenderBlocking = aRenderBlocking;
7067 return NS_OK;
7068}
7069
7070NS_IMETHODIMPnsresult
7071HttpBaseChannel::GetRenderBlocking(bool* aRenderBlocking) {
7072 *aRenderBlocking = mRenderBlocking;
7073 return NS_OK;
7074}
7075
7076NS_IMETHODIMPnsresult HttpBaseChannel::GetLastTransportStatus(
7077 nsresult* aLastTransportStatus) {
7078 return NS_ERROR_NOT_IMPLEMENTED;
7079}
7080
7081void HttpBaseChannel::SetFetchPriorityDOM(
7082 mozilla::dom::FetchPriority aPriority) {
7083 switch (aPriority) {
7084 case mozilla::dom::FetchPriority::Auto:
7085 SetFetchPriority(nsIClassOfService::FETCHPRIORITY_AUTO);
7086 return;
7087 case mozilla::dom::FetchPriority::High:
7088 SetFetchPriority(nsIClassOfService::FETCHPRIORITY_HIGH);
7089 return;
7090 case mozilla::dom::FetchPriority::Low:
7091 SetFetchPriority(nsIClassOfService::FETCHPRIORITY_LOW);
7092 return;
7093 default:
7094 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"
, 7094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " ")"); do { MOZ_CrashSequence(__null
, 7094); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
7095 }
7096}
7097
7098} // namespace net
7099} // namespace mozilla
7100#undef LOGORB