tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit a344785815b4cb21716c54a4449d5cfd4c94a06f
parent 8f2a3fac38ddb47db9216164a710c092b278720d
Author: Valentin Gosu <valentin.gosu@gmail.com>
Date:   Wed,  7 Jan 2026 09:26:06 +0000

Bug 1992512 - nsHTTPCompressConv::OnDataFinished should not QI listener off-main-thread r=necko-reviewers,kershaw

Since nsHTTPCompressConv::CheckListenerChain will return NS_OK in the
content process, that means OnDataFinished might be called even if
not all the listeners in the listener chain support being called
off-main-thread. This is the case for a JS implemented listener.
It is important to not QI a JS implemented listener off main thread.
Since the listener wouldn't benefit from OnDataFinished since it's
limited to the main thread, that means we can avoid calling it
entirely.

Differential Revision: https://phabricator.services.mozilla.com/D274324

Diffstat:
Mnetwerk/streamconv/converters/nsHTTPCompressConv.cpp | 44+++++++++++++++++++++++++-------------------
1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/netwerk/streamconv/converters/nsHTTPCompressConv.cpp b/netwerk/streamconv/converters/nsHTTPCompressConv.cpp @@ -1099,43 +1099,49 @@ uint32_t nsHTTPCompressConv::check_header(nsIInputStream* iStr, NS_IMETHODIMP nsHTTPCompressConv::CheckListenerChain() { - if (XRE_IsContentProcess() && - StaticPrefs::network_decompression_off_mainthread2()) { - // handle decompression OMT always. If the chain needs to be MT, - // we'll determine that in OnStartRequest and dispatch to MT - return NS_OK; - } + MOZ_ASSERT(NS_IsMainThread()); nsCOMPtr<nsIThreadRetargetableStreamListener> listener; { MutexAutoLock lock(mMutex); listener = do_QueryInterface(mListener); } - if (!listener) { - return NS_ERROR_NO_INTERFACE; + + nsresult rv = NS_ERROR_NO_INTERFACE; + if (listener) { + rv = listener->CheckListenerChain(); + } + + // handle decompression OMT always. If the chain needs to be MT, + // we'll determine that in OnStartRequest and dispatch to MT + bool alwaysOMT = XRE_IsContentProcess() && + StaticPrefs::network_decompression_off_mainthread2(); + + if (NS_FAILED(rv) && alwaysOMT) { + mDispatchToMainThread = true; + return NS_OK; } - return listener->CheckListenerChain(); + return rv; } NS_IMETHODIMP nsHTTPCompressConv::OnDataFinished(nsresult aStatus) { - nsCOMPtr<nsIThreadRetargetableStreamListener> listener; + if (mDispatchToMainThread && !NS_IsMainThread()) { + // If this is called off main thread, but the listener can only + // handle calls on the main thread, then just return. + // Also important - never QI the listener off main thread + // if mDispatchToMainThread is true, because the listener + // might be JS implemented and won't support that. + return NS_OK; + } + nsCOMPtr<nsIThreadRetargetableStreamListener> listener; { MutexAutoLock lock(mMutex); listener = do_QueryInterface(mListener); } if (listener) { - if (mDispatchToMainThread && !NS_IsMainThread()) { - nsCOMPtr<nsIRunnable> handler = NS_NewRunnableFunction( - "dispatch", [listener{std::move(listener)}, aStatus]() { - (void)listener->OnDataFinished(aStatus); - }); - - return NS_DispatchToMainThread(handler); - } - return listener->OnDataFinished(aStatus); }