Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h
Warning:line 80, column 7
Use of memory after it is released

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 RemoteMediaManagerChild.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/dom/media/ipc -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/ipc -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_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/dom/media/ipc -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/ipc -I /root/firefox-clang/xpcom/base -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/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-11-12-001017-1011516-1 -x c++ /root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp

/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.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#include "RemoteMediaManagerChild.h"
5
6#include "EMEDecoderModule.h"
7#include "ErrorList.h"
8#include "MP4Decoder.h"
9#include "PDMFactory.h"
10#include "PEMFactory.h"
11#include "PlatformDecoderModule.h"
12#include "PlatformEncoderModule.h"
13#include "RemoteAudioDecoder.h"
14#include "RemoteCDMProxy.h"
15#include "RemoteMediaDataDecoder.h"
16#include "RemoteMediaDataEncoder.h"
17#include "RemoteVideoDecoder.h"
18#include "VideoUtils.h"
19#include "mozilla/DataMutex.h"
20#include "mozilla/MozPromise.h"
21#include "mozilla/RemoteDecodeUtils.h"
22#include "mozilla/StaticPrefs_media.h"
23#include "mozilla/StaticPtr.h"
24#include "mozilla/SyncRunnable.h"
25#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild
26#include "mozilla/gfx/2D.h"
27#include "mozilla/gfx/DataSurfaceHelpers.h"
28#include "mozilla/gfx/gfxVars.h"
29#include "mozilla/ipc/BackgroundChild.h"
30#include "mozilla/ipc/Endpoint.h"
31#include "mozilla/ipc/PBackgroundChild.h"
32#include "mozilla/ipc/UtilityMediaServiceChild.h"
33#include "mozilla/layers/ISurfaceAllocator.h"
34#include "mozilla/layers/ImageDataSerializer.h"
35#include "nsContentUtils.h"
36#include "nsIObserver.h"
37#include "nsPrintfCString.h"
38
39#ifdef MOZ_WMF_MEDIA_ENGINE
40# include "MFMediaEngineChild.h"
41#endif
42
43#ifdef MOZ_WMF_CDM
44# include "MFCDMChild.h"
45#endif
46
47namespace mozilla {
48
49#define LOG(msg, ...) \
50 MOZ_LOG_FMT(gRemoteDecodeLog, LogLevel::Debug, msg, ##__VA_ARGS__)do { const ::mozilla::LogModule* moz_real_module = gRemoteDecodeLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, msg, ##__VA_ARGS__); } } while (0)
51#define LOGE(msg, ...) \
52 MOZ_LOG_FMT(gRemoteDecodeLog, LogLevel::Error, msg, ##__VA_ARGS__)do { const ::mozilla::LogModule* moz_real_module = gRemoteDecodeLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Error)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Error, msg, ##__VA_ARGS__); } } while (0)
53
54using namespace layers;
55using namespace gfx;
56
57using media::EncodeSupport;
58using media::EncodeSupportSet;
59
60// Used so that we only ever attempt to check if the RDD/GPU/Utility processes
61// should be launched serially. Protects sLaunchPromise
62StaticMutex sLaunchMutex;
63static EnumeratedArray<RemoteMediaIn, StaticRefPtr<GenericNonExclusivePromise>,
64 size_t(RemoteMediaIn::SENTINEL)>
65 sLaunchPromises MOZ_GUARDED_BY(sLaunchMutex)__attribute__((guarded_by(sLaunchMutex)));
66
67// Only modified on the main-thread, read on any thread. While it could be read
68// on the main thread directly, for clarity we force access via the DataMutex
69// wrapper.
70constinit static StaticDataMutex<StaticRefPtr<nsIThread>>
71 sRemoteMediaManagerChildThread("sRemoteMediaManagerChildThread");
72
73// Only accessed from sRemoteMediaManagerChildThread
74static EnumeratedArray<RemoteMediaIn, StaticRefPtr<RemoteMediaManagerChild>,
75 size_t(RemoteMediaIn::SENTINEL)>
76 sRemoteMediaManagerChildForProcesses;
77
78static StaticAutoPtr<nsTArray<RefPtr<Runnable>>> sRecreateTasks;
79
80// Only accessed from sRemoteMediaManagerChildThread. Settled when we are next
81// given an endpoint for the GPU process manager, or told that there is none.
82static StaticAutoPtr<MozPromiseHolder<GenericNonExclusivePromise>>
83 sGPUProcessRecreatedHolder;
84
85static RefPtr<GenericNonExclusivePromise> WaitForGPUProcessManager() {
86 auto* manager =
87 RemoteMediaManagerChild::GetSingleton(RemoteMediaIn::GpuProcess);
88 if (!manager) {
89 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE,
90 __func__);
91 }
92 if (!manager->CanSend()) {
93 if (!sGPUProcessRecreatedHolder) {
94 sGPUProcessRecreatedHolder =
95 new MozPromiseHolder<GenericNonExclusivePromise>();
96 }
97 RefPtr<GenericNonExclusivePromise> p =
98 sGPUProcessRecreatedHolder->Ensure(__func__);
99 return p->Then(
100 GetCurrentSerialEventTarget(), __func__,
101 [](const GenericNonExclusivePromise::ResolveOrRejectValue& aValue)
102 -> RefPtr<GenericNonExclusivePromise> {
103 if (aValue.IsReject()) {
104 return GenericNonExclusivePromise::CreateAndReject(
105 aValue.RejectValue(), __func__);
106 }
107 return WaitForGPUProcessManager();
108 });
109 }
110 return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
111}
112
113// Per-location codec support state collected from the remote processes.
114// mSupported holds the snapshot delivered over IPC (Nothing until the remote
115// process reports in); mHolder fulfills any pending EnsureCodecSupportFor()
116// promises once that snapshot arrives.
117struct CodecSupportState {
118 Maybe<media::MediaCodecsSupported> mSupported;
119 MozPromiseHolder<RemoteMediaManagerChild::CodecSupportPromise> mHolder;
120};
121
122// Used for protecting codec support information collected from different remote
123// processes.
124StaticMutex sProcessSupportedMutex;
125MOZ_GLOBINIT static EnumeratedArray<RemoteMediaIn, CodecSupportState,
126 size_t(RemoteMediaIn::SENTINEL)>
127 sCodecSupportState MOZ_GUARDED_BY(sProcessSupportedMutex)__attribute__((guarded_by(sProcessSupportedMutex)));
128
129class ShutdownObserver final : public nsIObserver {
130 public:
131 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:
132 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
133
134 protected:
135 ~ShutdownObserver() = default;
136};
137NS_IMPL_ISUPPORTS(ShutdownObserver, nsIObserver)MozExternalRefCountType ShutdownObserver::AddRef(void) { static_assert
(!std::is_destructible_v<ShutdownObserver>, "Reference-counted class "
"ShutdownObserver" " 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" ")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 137); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 137
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ShutdownObserver" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("ShutdownObserver" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"ShutdownObserver\" != nullptr" " (" "Must specify a name" ")"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 137); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShutdownObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 137); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("ShutdownObserver" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("ShutdownObserver"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType ShutdownObserver
::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" ")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 137); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 137
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ShutdownObserver" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("ShutdownObserver" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"ShutdownObserver\" != nullptr" " (" "Must specify a name" ")"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 137); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShutdownObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 137); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("ShutdownObserver" " not thread-safe"); const char* const nametmp
= "ShutdownObserver"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult ShutdownObserver
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 137); 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<ShutdownObserver, nsIObserver>, int32_t
( reinterpret_cast<char*>(static_cast<nsIObserver*>
((ShutdownObserver*)0x1000)) - reinterpret_cast<char*>(
(ShutdownObserver*)0x1000))}, {&mozilla::detail::kImplementedIID
<ShutdownObserver, nsISupports>, int32_t(reinterpret_cast
<char*>(static_cast<nsISupports*>( static_cast<
nsIObserver*>((ShutdownObserver*)0x1000))) - reinterpret_cast
<char*>((ShutdownObserver*)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; }
;
138
139NS_IMETHODIMPnsresult
140ShutdownObserver::Observe(nsISupports* aSubject, const char* aTopic,
141 const char16_t* aData) {
142 MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!strcmp(aTopic, "xpcom-shutdown"))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!strcmp(aTopic, "xpcom-shutdown"
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!strcmp(aTopic, \"xpcom-shutdown\")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!strcmp(aTopic, \"xpcom-shutdown\")"
")"); do { MOZ_CrashSequence(__null, 142); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
143 RemoteMediaManagerChild::Shutdown();
144 return NS_OK;
145}
146
147StaticRefPtr<ShutdownObserver> sObserver;
148
149/* static */
150void RemoteMediaManagerChild::Init() {
151 LOG("RemoteMediaManagerChild Init");
152
153 auto remoteDecoderManagerThread = sRemoteMediaManagerChildThread.Lock();
154 if (!*remoteDecoderManagerThread) {
155 LOG("RemoteMediaManagerChild's thread is created");
156 // We can't use a MediaThreadType::SUPERVISOR as the RemoteDecoderModule
157 // runs on it and dispatch synchronous tasks to the manager thread, should
158 // more than 4 concurrent videos being instantiated at the same time, we
159 // could end up in a deadlock.
160 RefPtr<nsIThread> childThread;
161 nsresult rv = NS_NewNamedThread(
162 "RemVidChild", getter_AddRefs(childThread),
163 NS_NewRunnableFunction(
164 "RemoteMediaManagerChild::InitPBackground", []() {
165 ipc::PBackgroundChild* bgActor =
166 ipc::BackgroundChild::GetOrCreateForCurrentThread();
167 NS_WARNING_ASSERTION(bgActor,do { if (!(bgActor)) { NS_DebugBreak(NS_DEBUG_WARNING, "Failed to start Background channel"
, "bgActor", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 168); } } while (false)
168 "Failed to start Background channel")do { if (!(bgActor)) { NS_DebugBreak(NS_DEBUG_WARNING, "Failed to start Background channel"
, "bgActor", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 168); } } while (false)
;
169 (void)bgActor;
170 }));
171
172 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 172); return; } } while (false)
;
173 *remoteDecoderManagerThread = childThread;
174 sRecreateTasks = new nsTArray<RefPtr<Runnable>>();
175 sObserver = new ShutdownObserver();
176 nsContentUtils::RegisterShutdownObserver(sObserver);
177 }
178}
179
180/* static */
181bool RemoteMediaManagerChild::IsGpuProcessDecodingAvailable() {
182 return StaticPrefs::media_gpu_process_decoder() &&
183 gfx::gfxVars::GPUProcessEnabled();
184}
185
186/* static */
187bool RemoteMediaManagerChild::IsGpuProcessEncodingAvailable() {
188 return StaticPrefs::media_gpu_process_encoder() &&
189 gfx::gfxVars::GPUProcessEnabled();
190}
191
192/* static */
193void RemoteMediaManagerChild::InitForGPUProcess(
194 Endpoint<PRemoteMediaManagerChild>&& aVideoManager) {
195 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()"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 195); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
196
197 Init();
198
199 auto remoteDecoderManagerThread = sRemoteMediaManagerChildThread.Lock();
200 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction
( "InitForContentRunnable", &OpenRemoteMediaManagerChildForProcess
, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))), 1)
))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 204); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 204); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
201 (*remoteDecoderManagerThread)do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction
( "InitForContentRunnable", &OpenRemoteMediaManagerChildForProcess
, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))), 1)
))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 204); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 204); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
202 ->Dispatch(NewRunnableFunction(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction
( "InitForContentRunnable", &OpenRemoteMediaManagerChildForProcess
, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))), 1)
))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 204); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 204); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
203 "InitForContentRunnable", &OpenRemoteMediaManagerChildForProcess,do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction
( "InitForContentRunnable", &OpenRemoteMediaManagerChildForProcess
, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))), 1)
))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 204); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 204); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
204 std::move(aVideoManager), RemoteMediaIn::GpuProcess)))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction
( "InitForContentRunnable", &OpenRemoteMediaManagerChildForProcess
, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))), 1)
))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 204); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 204); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
205}
206
207/* static */
208void RemoteMediaManagerChild::Shutdown() {
209 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()"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 209); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
210 LOG("RemoteMediaManagerChild Shutdown");
211
212 if (sObserver) {
213 nsContentUtils::UnregisterShutdownObserver(sObserver);
214 sObserver = nullptr;
215 }
216
217 {
218 StaticMutexAutoLock lock(sProcessSupportedMutex);
219 for (auto& state : sCodecSupportState) {
220 state.mHolder.RejectIfExists(NS_ERROR_ABORT, __func__);
221 }
222 }
223
224 nsCOMPtr<nsIThread> childThread;
225 {
226 auto remoteDecoderManagerThread = sRemoteMediaManagerChildThread.Lock();
227 childThread = remoteDecoderManagerThread->forget();
228 LOG("RemoteMediaManagerChild's thread is released");
229 }
230 if (childThread) {
231 MOZ_ALWAYS_SUCCEEDS(childThread->Dispatch(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
232 NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown", []() {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
233 for (auto& p : sRemoteMediaManagerChildForProcesses) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
234 if (p && p->CanSend()) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
235 p->Close();do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
236 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
237 p = nullptr;do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
238 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
239 {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
240 StaticMutexAutoLock lock(sLaunchMutex);do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
241 for (auto& p : sLaunchPromises) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
242 p = nullptr;do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
243 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
244 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
245 if (sGPUProcessRecreatedHolder) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
246 sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT,do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
247 __func__);do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
248 sGPUProcessRecreatedHolder = nullptr;do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
249 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
250 ipc::BackgroundChild::CloseForCurrentThread();do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
251 })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(childThread->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaManagerChild::Shutdown"
, []() { for (auto& p : sRemoteMediaManagerChildForProcesses
) { if (p && p->CanSend()) { p->Close(); } p = nullptr
; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p
: sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder
) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT
, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild
::CloseForCurrentThread(); })))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 251); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(childThread->Dispatch( NS_NewRunnableFunction(\"dom::RemoteMediaManagerChild::Shutdown\", []() { for (auto& p : sRemoteMediaManagerChildForProcesses) { if (p && p->CanSend()) { p->Close(); } p = nullptr; } { StaticMutexAutoLock lock(sLaunchMutex); for (auto& p : sLaunchPromises) { p = nullptr; } } if (sGPUProcessRecreatedHolder) { sGPUProcessRecreatedHolder->RejectIfExists(NS_ERROR_ABORT, __func__); sGPUProcessRecreatedHolder = nullptr; } ipc::BackgroundChild::CloseForCurrentThread(); })))"
")"); do { MOZ_CrashSequence(__null, 251); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
252 childThread->Shutdown();
253 sRecreateTasks = nullptr;
254 }
255}
256
257/* static */ void RemoteMediaManagerChild::RunWhenGPUProcessRecreated(
258 const RemoteMediaManagerChild* aDyingManager,
259 already_AddRefed<Runnable> aTask) {
260 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
261 if (!managerThread) {
262 // We've been shutdown, bail.
263 return;
264 }
265 MOZ_ASSERT(managerThread->IsOnCurrentThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(managerThread->IsOnCurrentThread())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(managerThread->IsOnCurrentThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("managerThread->IsOnCurrentThread()"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "managerThread->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 265); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
266
267 // If we've already been recreated, then run the task immediately. If we were
268 // not given an endpoint, then the GPU process, or decoding in it, is disabled
269 // and we will not be recreated, so run the task immediately as well.
270 auto* manager = GetSingleton(RemoteMediaIn::GpuProcess);
271 if (!manager || (manager != aDyingManager && manager->CanSend())) {
272 RefPtr<Runnable> task = aTask;
273 task->Run();
274 } else {
275 sRecreateTasks->AppendElement(aTask);
276 }
277}
278
279/* static */
280RemoteMediaManagerChild* RemoteMediaManagerChild::GetSingleton(
281 RemoteMediaIn aLocation) {
282 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
283 if (!managerThread) {
284 // We've been shutdown, bail.
285 return nullptr;
286 }
287 MOZ_ASSERT(managerThread->IsOnCurrentThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(managerThread->IsOnCurrentThread())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(managerThread->IsOnCurrentThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("managerThread->IsOnCurrentThread()"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "managerThread->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 287); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
288 switch (aLocation) {
289 case RemoteMediaIn::GpuProcess:
290 case RemoteMediaIn::RddProcess:
291 case RemoteMediaIn::UtilityProcess_Generic:
292 case RemoteMediaIn::UtilityProcess_AppleMedia:
293 case RemoteMediaIn::UtilityProcess_WMF:
294 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM:
295 return sRemoteMediaManagerChildForProcesses[aLocation];
296 default:
297 MOZ_CRASH("Unexpected RemoteMediaIn variant")do { do { } while (false); MOZ_ReportCrash("" "Unexpected RemoteMediaIn variant"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 297); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected RemoteMediaIn variant"
")"); do { MOZ_CrashSequence(__null, 297); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
298 return nullptr;
299 }
300}
301
302/* static */
303nsCOMPtr<nsISerialEventTarget> RemoteMediaManagerChild::GetManagerThread() {
304 auto remoteDecoderManagerThread = sRemoteMediaManagerChildThread.Lock();
305 return nsCOMPtr<nsISerialEventTarget>(*remoteDecoderManagerThread);
306}
307
308/* static */
309media::DecodeSupportSet RemoteMediaManagerChild::Supports(
310 RemoteMediaIn aLocation, const SupportDecoderParams& aParams,
311 DecoderDoctorDiagnostics* aDiagnostics) {
312 if (aLocation == RemoteMediaIn::GpuProcess &&
313 !IsGpuProcessDecodingAvailable()) {
314 return {};
315 }
316
317 Maybe<media::MediaCodecsSupported> supported;
318 switch (aLocation) {
319 case RemoteMediaIn::GpuProcess:
320 case RemoteMediaIn::RddProcess:
321 case RemoteMediaIn::UtilityProcess_AppleMedia:
322 case RemoteMediaIn::UtilityProcess_Generic:
323 case RemoteMediaIn::UtilityProcess_WMF:
324 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM: {
325 StaticMutexAutoLock lock(sProcessSupportedMutex);
326 supported = sCodecSupportState[aLocation].mSupported;
327 break;
328 }
329 default:
330 return {};
331 }
332#ifdef MOZ_WIDGET_ANDROID
333 // The GPU process reports its support without a CDM. With a CDM, audio may
334 // be decoded there, and video may use the MediaCodec software decoders,
335 // since decoding always uses MediaCodec.
336 if (aLocation == RemoteMediaIn::GpuProcess && aParams.mCDM) {
337 // This matches what KeySystemConfig uses. If the GPU process is unable to
338 // create the decoder, creation fails since it cannot fallback to software
339 // decoding.
340 supported = Some(gfx::gfxVars::PlatformMediaCodecsSupported());
341 }
342#endif
343 if (!supported) {
344 // We haven't received the correct information yet from either the GPU or
345 // the RDD process nor the Utility process.
346 if (aLocation == RemoteMediaIn::UtilityProcess_Generic ||
347 aLocation == RemoteMediaIn::UtilityProcess_AppleMedia ||
348 aLocation == RemoteMediaIn::UtilityProcess_WMF ||
349 aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
350 LaunchUtilityProcessIfNeeded(aLocation);
351 }
352 if (aLocation == RemoteMediaIn::RddProcess) {
353 // Ensure the RDD process got started.
354 // TODO: This can be removed once bug 1684991 is fixed.
355 LaunchRDDProcessIfNeeded();
356 }
357
358 // Assume the format is supported to prevent false negative, if the remote
359 // process supports that specific track type. HW support is unknown until
360 // the process reports in, so conservatively report SW-only.
361 const bool isVideo = aParams.mConfig.IsVideo();
362 const bool isAudio = aParams.mConfig.IsAudio();
363 const auto trackSupport = GetTrackSupport(aLocation);
364 if (isVideo) {
365 // Special condition for HEVC, which can only be supported in specific
366 // process. As HEVC support is still a experimental feature, we don't want
367 // to report support for it arbitrarily.
368 if (MP4Decoder::IsHEVC(aParams.mConfig.mMimeType)) {
369 if (!StaticPrefs::media_hevc_enabled()) {
370 return {};
371 }
372#if defined(XP_WIN)
373 if (aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM ||
374 aLocation == RemoteMediaIn::GpuProcess) {
375 // No software support in most cases for HEVC so guess hardware.
376 return {media::DecodeSupport::HardwareDecode};
377 }
378 return {};
379#else
380 return trackSupport.contains(TrackSupport::DecodeVideo)
381 ? media::
382 DecodeSupportSet{media::DecodeSupport::SoftwareDecode}
383 : media::DecodeSupportSet{};
384#endif
385 }
386 return trackSupport.contains(TrackSupport::DecodeVideo)
387 ? media::DecodeSupportSet{media::DecodeSupport::SoftwareDecode}
388 : media::DecodeSupportSet{};
389 }
390 if (isAudio) {
391 return trackSupport.contains(TrackSupport::DecodeAudio)
392 ? media::DecodeSupportSet{media::DecodeSupport::SoftwareDecode}
393 : media::DecodeSupportSet{};
394 }
395 MOZ_ASSERT_UNREACHABLE("Not audio and video?!")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: "
"Not audio and video?!" ")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Not audio and video?!" ")"); do {
MOZ_CrashSequence(__null, 395); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
396 return {};
397 }
398
399 // We can ignore the SupportDecoderParams argument for now as creation of the
400 // decoder will actually fail later and fallback PDMs will be tested on later.
401 return PDMFactory::SupportsMimeType(aParams.MimeType(), *supported,
402 aLocation);
403}
404
405/* static */
406RefPtr<PlatformDecoderModule::CreateDecoderPromise>
407RemoteMediaManagerChild::CreateAudioDecoder(const CreateDecoderParams& aParams,
408 RemoteMediaIn aLocation) {
409 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
410 if (!managerThread) {
411 // We got shutdown.
412 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
413 NS_ERROR_DOM_MEDIA_CANCELED, __func__);
414 }
415
416 if (!GetTrackSupport(aLocation).contains(TrackSupport::DecodeAudio)) {
417 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
418 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
419 nsPrintfCString("%s doesn't support audio decoding",
420 RemoteMediaInToStr(aLocation))
421 .get()),
422 __func__);
423 }
424
425 if (!aParams.mMediaEngineId &&
426 aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
427 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
428 MediaResult(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR,
429 nsPrintfCString("%s only support for media engine playback",
430 RemoteMediaInToStr(aLocation))
431 .get()),
432 __func__);
433 }
434
435 if (aLocation == RemoteMediaIn::GpuProcess && !aParams.mCDM) {
436 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
437 MediaResult(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR,
438 "GPU process requires a CDM to perform audio decoding"),
439 __func__);
440 }
441
442 RefPtr<GenericNonExclusivePromise> launchPromise;
443 if (StaticPrefs::media_utility_process_enabled() &&
444 (aLocation == RemoteMediaIn::UtilityProcess_Generic ||
445 aLocation == RemoteMediaIn::UtilityProcess_AppleMedia ||
446 aLocation == RemoteMediaIn::UtilityProcess_WMF)) {
447 launchPromise = LaunchUtilityProcessIfNeeded(aLocation);
448 } else if (aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
449 launchPromise = LaunchUtilityProcessIfNeeded(aLocation);
450 } else if (aLocation == RemoteMediaIn::GpuProcess) {
451 launchPromise = EnsureGPUProcessReady();
452 } else if (StaticPrefs::media_allow_audio_non_utility() || aParams.mCDM) {
453 launchPromise = LaunchRDDProcessIfNeeded();
454 } else {
455 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
456 MediaResult(
457 NS_ERROR_DOM_MEDIA_DENIED_IN_NON_UTILITY,
458 nsPrintfCString("%s is not allowed to perform audio decoding",
459 RemoteMediaInToStr(aLocation))
460 .get()),
461 __func__);
462 }
463 LOG("Create audio decoder in {}", RemoteMediaInToStr(aLocation));
464
465 return launchPromise->Then(
466 managerThread, __func__,
467 [params = CreateDecoderParamsForAsync(aParams), aLocation](bool) mutable {
468 auto child = MakeRefPtr<RemoteAudioDecoderChild>(aLocation);
469 MediaResult result =
470 child->InitIPDL(params.AudioConfig(), params.mOptions,
471 params.mMediaEngineId, params.mCDM);
472 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0)))) {
473 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
474 result, __func__);
475 }
476 return Construct(std::move(child), std::move(params), aLocation);
477 },
478 [aLocation](nsresult aResult) {
479 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
480 MediaResult(aResult,
481 nsPrintfCString("Couldn't create decoder in %s process",
482 RemoteMediaInToStr(aLocation))
483 .get()),
484 __func__);
485 });
486}
487
488/* static */
489RefPtr<PlatformDecoderModule::CreateDecoderPromise>
490RemoteMediaManagerChild::CreateVideoDecoder(const CreateDecoderParams& aParams,
491 RemoteMediaIn aLocation) {
492 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
493 if (!managerThread) {
494 // We got shutdown.
495 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
496 NS_ERROR_DOM_MEDIA_CANCELED, __func__);
497 }
498
499 if (!aParams.mKnowsCompositor && aLocation == RemoteMediaIn::GpuProcess) {
500 // We don't have an image bridge; don't attempt to decode in the GPU
501 // process.
502 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
503 NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR, __func__);
504 }
505
506 if (!GetTrackSupport(aLocation).contains(TrackSupport::DecodeVideo)) {
507 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
508 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
509 nsPrintfCString("%s doesn't support video decoding",
510 RemoteMediaInToStr(aLocation))
511 .get()),
512 __func__);
513 }
514
515 if (!aParams.mMediaEngineId &&
516 aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
517 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
518 MediaResult(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR,
519 nsPrintfCString("%s only support for media engine playback",
520 RemoteMediaInToStr(aLocation))
521 .get()),
522 __func__);
523 }
524
525 MOZ_ASSERT(aLocation != RemoteMediaIn::Unspecified)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLocation != RemoteMediaIn::Unspecified)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aLocation != RemoteMediaIn::Unspecified))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLocation != RemoteMediaIn::Unspecified"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 525); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation != RemoteMediaIn::Unspecified"
")"); do { MOZ_CrashSequence(__null, 525); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
526
527 RefPtr<GenericNonExclusivePromise> p;
528 if (aLocation == RemoteMediaIn::GpuProcess) {
529 p = EnsureGPUProcessReady();
530 } else if (aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
531 p = LaunchUtilityProcessIfNeeded(aLocation);
532 } else {
533 p = LaunchRDDProcessIfNeeded();
534 }
535 LOG("Create video decoder in {}", RemoteMediaInToStr(aLocation));
536
537 return p->Then(
538 managerThread, __func__,
539 [aLocation, params = CreateDecoderParamsForAsync(aParams)](bool) mutable {
540 auto child = MakeRefPtr<RemoteVideoDecoderChild>(aLocation);
541 MediaResult result = child->InitIPDL(
542 params.VideoConfig(), params.mRate.mValue, params.mOptions,
543 params.mMediaEngineId, params.mTrackingId, params.mCDM);
544 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0)))) {
545 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
546 result, __func__);
547 }
548 return Construct(std::move(child), std::move(params), aLocation);
549 },
550 [aLocation](nsresult aResult) {
551 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
552 MediaResult(aResult,
553 nsPrintfCString("Couldn't create decoder in %s process",
554 RemoteMediaInToStr(aLocation))
555 .get()),
556 __func__);
557 });
558}
559
560/* static */
561RefPtr<RemoteCDMProxy> RemoteMediaManagerChild::CreateCDM(
562 dom::MediaKeys* aKeys, const nsAString& aKeySystem,
563 bool aDistinctiveIdentifierRequired, bool aPersistentStateRequired) {
564 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()"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 564); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
565
566 if (!StaticPrefs::media_ffvpx_hw_enabled()) {
567 return nullptr;
568 }
569
570 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
571 if (!managerThread) {
572 // We got shutdown.
573 return nullptr;
574 }
575
576 // The CDM must be in the same process as the audio and video decoders which
577 // use it. We use the GPU process if enabled, and RemoteCDMProxy will fallback
578 // to the RDD process if it becomes disabled before it initializes.
579 RemoteMediaIn location;
580 RefPtr<GenericNonExclusivePromise> p;
581 if (IsGpuProcessDecodingAvailable()) {
582 location = RemoteMediaIn::GpuProcess;
583 p = EnsureGPUProcessReady();
584 } else {
585 location = RemoteMediaIn::RddProcess;
586 p = LaunchRDDProcessIfNeeded();
587 }
588 LOG("Create CDM in {}", RemoteMediaInToStr(location));
589
590 return MakeRefPtr<RemoteCDMProxy>(
591 std::move(managerThread), std::move(p), location, aKeys, aKeySystem,
592 aDistinctiveIdentifierRequired, aPersistentStateRequired);
593}
594
595/* static */
596RefPtr<PlatformDecoderModule::CreateDecoderPromise>
597RemoteMediaManagerChild::Construct(RefPtr<RemoteDecoderChild>&& aChild,
598 CreateDecoderParamsForAsync&& aParams,
599 RemoteMediaIn aLocation) {
600 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
601 if (!managerThread) {
602 // We got shutdown.
603 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
604 NS_ERROR_DOM_MEDIA_CANCELED, __func__);
605 }
606 MOZ_ASSERT(managerThread->IsOnCurrentThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(managerThread->IsOnCurrentThread())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(managerThread->IsOnCurrentThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("managerThread->IsOnCurrentThread()"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "managerThread->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 606); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
607
608 RefPtr<PlatformDecoderModule::CreateDecoderPromise> p =
609 aChild->SendConstruct()->Then(
610 managerThread, __func__,
611 [child = std::move(aChild),
612 params = std::move(aParams)](MediaResult aResult) {
613 if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
614 // We will never get to use this remote decoder, tear it down.
615 child->DestroyIPDL();
616 return PlatformDecoderModule::CreateDecoderPromise::
617 CreateAndReject(aResult, __func__);
618 }
619 if (params.mCDM) {
620 if (auto* cdm = params.mCDM->AsRemoteCDMProxy()) {
621 return PlatformDecoderModule::CreateDecoderPromise::
622 CreateAndResolve(
623 MakeRefPtr<EMEMediaDataDecoderProxy>(
624 params,
625 MakeAndAddRef<RemoteMediaDataDecoder>(child), cdm),
626 __func__);
627 }
628 return PlatformDecoderModule::CreateDecoderPromise::
629 CreateAndReject(
630 NS_ERROR_DOM_MEDIA_CDM_PROXY_NOT_SUPPORTED_ERR, __func__);
631 }
632 return PlatformDecoderModule::CreateDecoderPromise::
633 CreateAndResolve(MakeRefPtr<RemoteMediaDataDecoder>(child),
634 __func__);
635 },
636 [aLocation](const mozilla::ipc::ResponseRejectReason& aReason) {
637 // The parent has died.
638 nsresult err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_UTILITY_ERR;
639 if (aLocation == RemoteMediaIn::GpuProcess ||
640 aLocation == RemoteMediaIn::RddProcess) {
641 err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_RDD_OR_GPU_ERR;
642 } else if (aLocation ==
643 RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
644 err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_MF_CDM_ERR;
645 }
646 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
647 err, __func__);
648 });
649 return p;
650}
651
652/* static */
653EncodeSupportSet RemoteMediaManagerChild::Supports(RemoteMediaIn aLocation,
654 CodecType aCodec) {
655 if (aLocation == RemoteMediaIn::GpuProcess &&
656 !IsGpuProcessEncodingAvailable()) {
657 return EncodeSupportSet{};
658 }
659
660 Maybe<media::MediaCodecsSupported> supported;
661 switch (aLocation) {
662 case RemoteMediaIn::GpuProcess:
663 case RemoteMediaIn::RddProcess:
664 case RemoteMediaIn::UtilityProcess_AppleMedia:
665 case RemoteMediaIn::UtilityProcess_Generic:
666 case RemoteMediaIn::UtilityProcess_WMF:
667 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM: {
668 StaticMutexAutoLock lock(sProcessSupportedMutex);
669 supported = sCodecSupportState[aLocation].mSupported;
670 break;
671 }
672 default:
673 return EncodeSupportSet{};
674 }
675 if (!supported) {
676 // We haven't received the correct information yet from either the GPU or
677 // the RDD process nor the Utility process.
678 if (aLocation == RemoteMediaIn::UtilityProcess_Generic ||
679 aLocation == RemoteMediaIn::UtilityProcess_AppleMedia ||
680 aLocation == RemoteMediaIn::UtilityProcess_WMF ||
681 aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
682 LaunchUtilityProcessIfNeeded(aLocation);
683 }
684 if (aLocation == RemoteMediaIn::RddProcess) {
685 // Ensure the RDD process got started.
686 // TODO: This can be removed once bug 1684991 is fixed.
687 LaunchRDDProcessIfNeeded();
688 }
689
690 // Assume the format is supported to prevent false negative, if the remote
691 // process supports that specific track type.
692 const auto trackSupport = GetTrackSupport(aLocation);
693 if (IsVideo(aCodec)) {
694 // Special condition for HEVC, which can only be supported in specific
695 // process. As HEVC support is still a experimental feature, we don't want
696 // to report support for it arbitrarily.
697 bool supported = trackSupport.contains(TrackSupport::EncodeVideo);
698 if (aCodec == CodecType::H265) {
699 if (!StaticPrefs::media_hevc_enabled()) {
700 return EncodeSupportSet{};
701 }
702#if defined(XP_WIN)
703 supported = aLocation == RemoteMediaIn::GpuProcess;
704#endif
705 }
706 return supported ? EncodeSupportSet{EncodeSupport::SoftwareEncode}
707 : EncodeSupportSet{};
708 }
709 if (IsAudio(aCodec)) {
710 return trackSupport.contains(TrackSupport::EncodeAudio)
711 ? EncodeSupportSet{EncodeSupport::SoftwareEncode}
712 : EncodeSupportSet{};
713 }
714 MOZ_ASSERT_UNREACHABLE("Not audio and video?!")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: "
"Not audio and video?!" ")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Not audio and video?!" ")"); do {
MOZ_CrashSequence(__null, 714); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
715 return EncodeSupportSet{};
716 }
717
718 // We can ignore the rest of EncoderConfig for now as creation of the encoder
719 // will actually fail later and fallback PEMs will be tested on later.
720 return PEMFactory::SupportsCodec(aCodec, *supported, aLocation);
721}
722
723/* static */ RefPtr<PlatformEncoderModule::CreateEncoderPromise>
724RemoteMediaManagerChild::InitializeEncoder(
725 RefPtr<RemoteMediaDataEncoder>&& aEncoder, const EncoderConfig& aConfig) {
726 RemoteMediaIn location = aEncoder->GetLocation();
727
728 TrackSupport required;
729 if (aConfig.IsAudio()) {
730 required = TrackSupport::EncodeAudio;
731 } else if (aConfig.IsVideo()) {
732 required = TrackSupport::EncodeVideo;
733 } else {
734 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
735 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
736 nsPrintfCString("%s doesn't support encoding",
737 RemoteMediaInToStr(location))
738 .get()),
739 __func__);
740 }
741
742 if (!GetTrackSupport(location).contains(required)) {
743 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
744 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
745 nsPrintfCString("%s doesn't support encoding",
746 RemoteMediaInToStr(location))
747 .get()),
748 __func__);
749 }
750
751 auto managerThread = aEncoder->GetManagerThread();
752 if (!managerThread) {
753 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
754 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED, "Thread shutdown"_ns),
755 __func__);
756 }
757
758 MOZ_ASSERT(location != RemoteMediaIn::Unspecified)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(location != RemoteMediaIn::Unspecified)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(location != RemoteMediaIn::Unspecified))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("location != RemoteMediaIn::Unspecified"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location != RemoteMediaIn::Unspecified"
")"); do { MOZ_CrashSequence(__null, 758); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
759
760 RefPtr<GenericNonExclusivePromise> p;
761 if (location == RemoteMediaIn::UtilityProcess_Generic ||
762 location == RemoteMediaIn::UtilityProcess_AppleMedia ||
763 location == RemoteMediaIn::UtilityProcess_WMF) {
764 p = LaunchUtilityProcessIfNeeded(location);
765 } else if (location == RemoteMediaIn::GpuProcess) {
766 p = EnsureGPUProcessReady();
767 } else if (location == RemoteMediaIn::RddProcess) {
768 p = LaunchRDDProcessIfNeeded();
769 } else {
770 p = GenericNonExclusivePromise::CreateAndReject(
771 NS_ERROR_DOM_MEDIA_DENIED_IN_NON_UTILITY, __func__);
772 }
773 LOG("Creating {} encoder type {} in {}",
774 aConfig.IsAudio() ? "audio" : "video", static_cast<int>(aConfig.mCodec),
775 RemoteMediaInToStr(location));
776
777 return p->Then(
778 managerThread, __func__,
779 [encoder = std::move(aEncoder), aConfig](bool) {
780 auto* manager = GetSingleton(encoder->GetLocation());
781 if (!manager) {
782 LOG("Create encoder in {} failed, shutdown",
783 RemoteMediaInToStr(encoder->GetLocation()));
784 // We got shutdown.
785 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
786 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
787 "Remote manager not available"),
788 __func__);
789 }
790 if (!manager->SendPRemoteEncoderConstructor(encoder->GetChild(),
791 aConfig)) {
792 LOG("Create encoder in {} failed, send failed",
793 RemoteMediaInToStr(encoder->GetLocation()));
794 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
795 MediaResult(NS_ERROR_NOT_AVAILABLE,
796 "Failed to construct encoder actor"),
797 __func__);
798 }
799 return encoder->Construct();
800 },
801 [location](nsresult aResult) {
802 LOG("Create encoder in {} failed, cannot start process",
803 RemoteMediaInToStr(location));
804 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
805 MediaResult(aResult,
806 nsPrintfCString("Couldn't create encoder in %s process",
807 RemoteMediaInToStr(location))
808 .get()),
809 __func__);
810 });
811}
812
813/* static */
814RefPtr<GenericNonExclusivePromise>
815RemoteMediaManagerChild::LaunchRDDProcessIfNeeded() {
816 MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
" (" "Only supported from a content process." ")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 817); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Only supported from a content process." ")"); do { MOZ_CrashSequence
(__null, 817); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
4
Assuming the condition is false
5
Taking false branch
6
Loop condition is false. Exiting loop
817 "Only supported from a content process.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
" (" "Only supported from a content process." ")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 817); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Only supported from a content process." ")"); do { MOZ_CrashSequence
(__null, 817); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
818
819 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
820 if (!managerThread) {
7
Taking false branch
821 // We got shutdown.
822 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
823 __func__);
824 }
825
826 StaticMutexAutoLock lock(sLaunchMutex);
827 auto& rddLaunchPromise = sLaunchPromises[RemoteMediaIn::RddProcess];
828 if (rddLaunchPromise) {
8
Assuming the condition is false
9
Taking false branch
829 return rddLaunchPromise;
830 }
831
832 // We have a couple possible states here. We are in a content process
833 // and:
834 // 1) the RDD process has never been launched. RDD should be launched
835 // and the IPC connections setup.
836 // 2) the RDD process has been launched, but this particular content
837 // process has not setup (or has lost) its IPC connection.
838 // In the code below, we assume we need to launch the RDD process and
839 // setup the IPC connections. However, if the manager thread for
840 // RemoteMediaManagerChild is available we do a quick check to see
841 // if we can send (meaning the IPC channel is open). If we can send,
842 // then no work is necessary. If we can't send, then we call
843 // LaunchRDDProcess which will launch RDD if necessary, and setup the
844 // IPC connections between *this* content process and the RDD process.
845
846 RefPtr<GenericNonExclusivePromise> p = InvokeAsync(
847 managerThread, __func__, []() -> RefPtr<GenericNonExclusivePromise> {
848 auto* rps = GetSingleton(RemoteMediaIn::RddProcess);
849 if (rps && rps->CanSend()) {
850 return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
851 }
852 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
853 ipc::PBackgroundChild* bgActor =
854 ipc::BackgroundChild::GetForCurrentThread();
855 if (!managerThread || NS_WARN_IF(!bgActor)NS_warn_if_impl(!bgActor, "!bgActor", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 855)
) {
856 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
857 __func__);
858 }
859
860 return bgActor->SendEnsureRDDProcessAndCreateBridge()->Then(
861 managerThread, __func__,
862 [](ipc::PBackgroundChild::EnsureRDDProcessAndCreateBridgePromise::
863 ResolveOrRejectValue&& aResult) {
864 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
865 if (!managerThread || aResult.IsReject()) {
866 // The parent process died or we got shutdown
867 return GenericNonExclusivePromise::CreateAndReject(
868 NS_ERROR_FAILURE, __func__);
869 }
870 nsresult rv = std::get<0>(aResult.ResolveValue());
871 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
872 return GenericNonExclusivePromise::CreateAndReject(rv,
873 __func__);
874 }
875 OpenRemoteMediaManagerChildForProcess(
876 std::get<1>(std::move(aResult.ResolveValue())),
877 RemoteMediaIn::RddProcess);
878 return GenericNonExclusivePromise::CreateAndResolve(true,
879 __func__);
880 });
881 });
882
883 // This should not be dispatched to a threadpool thread, so use managerThread
884 p = p->Then(
10
Calling copy assignment operator for 'RefPtr<mozilla::MozPromise<bool, nsresult, false>>'
32
Returning; memory was released
885 managerThread, __func__,
886 [](const GenericNonExclusivePromise::ResolveOrRejectValue& aResult) {
887 StaticMutexAutoLock lock(sLaunchMutex);
888 sLaunchPromises[RemoteMediaIn::RddProcess] = nullptr;
889 return GenericNonExclusivePromise::CreateAndResolveOrReject(aResult,
890 __func__);
891 });
33
Calling '~ThenCommand'
892
893 rddLaunchPromise = p;
894 return rddLaunchPromise;
895}
896
897/* static */
898RefPtr<GenericNonExclusivePromise>
899RemoteMediaManagerChild::EnsureGPUProcessReady() {
900 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
901 if (!managerThread) {
902 // We got shutdown.
903 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
904 __func__);
905 }
906
907 return InvokeAsync(managerThread, __func__, &WaitForGPUProcessManager);
908}
909
910/* static */
911RefPtr<GenericNonExclusivePromise>
912RemoteMediaManagerChild::LaunchUtilityProcessIfNeeded(RemoteMediaIn aLocation) {
913 MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
" (" "Only supported from a content process." ")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 914); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Only supported from a content process." ")"); do { MOZ_CrashSequence
(__null, 914); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
914 "Only supported from a content process.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
" (" "Only supported from a content process." ")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 914); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Only supported from a content process." ")"); do { MOZ_CrashSequence
(__null, 914); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
915
916 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
917 if (!managerThread) {
918 // We got shutdown.
919 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
920 __func__);
921 }
922
923 MOZ_ASSERT(aLocation == RemoteMediaIn::UtilityProcess_Generic ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLocation == RemoteMediaIn::UtilityProcess_Generic ||
aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation
== RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLocation == RemoteMediaIn::
UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia
|| aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation
== RemoteMediaIn::UtilityProcess_MFMediaEngineCDM))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 926); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 926); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
924 aLocation == RemoteMediaIn::UtilityProcess_AppleMedia ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLocation == RemoteMediaIn::UtilityProcess_Generic ||
aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation
== RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLocation == RemoteMediaIn::
UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia
|| aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation
== RemoteMediaIn::UtilityProcess_MFMediaEngineCDM))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 926); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 926); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
925 aLocation == RemoteMediaIn::UtilityProcess_WMF ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLocation == RemoteMediaIn::UtilityProcess_Generic ||
aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation
== RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLocation == RemoteMediaIn::
UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia
|| aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation
== RemoteMediaIn::UtilityProcess_MFMediaEngineCDM))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 926); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 926); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
926 aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLocation == RemoteMediaIn::UtilityProcess_Generic ||
aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation
== RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLocation == RemoteMediaIn::
UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia
|| aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation
== RemoteMediaIn::UtilityProcess_MFMediaEngineCDM))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 926); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 926); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
927 StaticMutexAutoLock lock(sLaunchMutex);
928 auto& utilityLaunchPromise = sLaunchPromises[aLocation];
929
930 if (utilityLaunchPromise) {
931 return utilityLaunchPromise;
932 }
933
934 // We have a couple possible states here. We are in a content process
935 // and:
936 // 1) the Utility process has never been launched. Utility should be launched
937 // and the IPC connections setup.
938 // 2) the Utility process has been launched, but this particular content
939 // process has not setup (or has lost) its IPC connection.
940 // In the code below, we assume we need to launch the Utility process and
941 // setup the IPC connections. However, if the manager thread for
942 // RemoteMediaManagerChild is available we do a quick check to see
943 // if we can send (meaning the IPC channel is open). If we can send,
944 // then no work is necessary. If we can't send, then we call
945 // LaunchUtilityProcess which will launch Utility if necessary, and setup the
946 // IPC connections between *this* content process and the Utility process.
947
948 RefPtr<GenericNonExclusivePromise> p = InvokeAsync(
949 managerThread, __func__,
950 [aLocation]() -> RefPtr<GenericNonExclusivePromise> {
951 auto* rps = GetSingleton(aLocation);
952 if (rps && rps->CanSend()) {
953 return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
954 }
955 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
956 ipc::PBackgroundChild* bgActor =
957 ipc::BackgroundChild::GetForCurrentThread();
958 if (!managerThread || NS_WARN_IF(!bgActor)NS_warn_if_impl(!bgActor, "!bgActor", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 958)
) {
959 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
960 __func__);
961 }
962
963 return bgActor->SendEnsureUtilityProcessAndCreateBridge(aLocation)
964 ->Then(managerThread, __func__,
965 [aLocation](ipc::PBackgroundChild::
966 EnsureUtilityProcessAndCreateBridgePromise::
967 ResolveOrRejectValue&& aResult)
968 -> RefPtr<GenericNonExclusivePromise> {
969 nsCOMPtr<nsISerialEventTarget> managerThread =
970 GetManagerThread();
971 if (!managerThread || aResult.IsReject()) {
972 // The parent process died or we got shutdown
973 return GenericNonExclusivePromise::CreateAndReject(
974 NS_ERROR_FAILURE, __func__);
975 }
976 nsresult rv = std::get<0>(aResult.ResolveValue());
977 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
978 return GenericNonExclusivePromise::CreateAndReject(
979 rv, __func__);
980 }
981 OpenRemoteMediaManagerChildForProcess(
982 std::get<1>(std::move(aResult.ResolveValue())),
983 aLocation);
984 return GenericNonExclusivePromise::CreateAndResolve(
985 true, __func__);
986 });
987 });
988
989 // Let's make sure this promise is also run on the managerThread to avoid
990 // situations where it would be run on a threadpool thread.
991 // During bug 1794988 this was happening when enabling Utility for audio on
992 // Android when running the sequence of tests
993 // dom/media/test/test_access_control.html
994 // dom/media/test/test_arraybuffer.html
995 //
996 // We would have a launched utility process but the promises would not have
997 // been cleared, so any subsequent tentative to perform audio decoding would
998 // think the process is not yet ran and it would try to wait on the pending
999 // promises.
1000 p = p->Then(
1001 managerThread, __func__,
1002 [aLocation](
1003 const GenericNonExclusivePromise::ResolveOrRejectValue& aResult) {
1004 StaticMutexAutoLock lock(sLaunchMutex);
1005 sLaunchPromises[aLocation] = nullptr;
1006 return GenericNonExclusivePromise::CreateAndResolveOrReject(aResult,
1007 __func__);
1008 });
1009 utilityLaunchPromise = p;
1010 return utilityLaunchPromise;
1011}
1012
1013/* static */
1014TrackSupportSet RemoteMediaManagerChild::GetTrackSupport(
1015 RemoteMediaIn aLocation) {
1016 TrackSupportSet s{TrackSupport::None};
1017 switch (aLocation) {
1018 case RemoteMediaIn::GpuProcess:
1019 s = TrackSupport::DecodeVideo;
1020 if (StaticPrefs::media_use_remote_encoder_video_platform()) {
1021 s += TrackSupport::EncodeVideo;
1022 }
1023#ifdef ANDROID
1024 // Audio decoding is only permitted with a CDM, so that the CDM may be
1025 // shared with the video decoder. RemoteDecoderModule::Supports enforces
1026 // this.
1027 s += TrackSupport::DecodeAudio;
1028#endif
1029 break;
1030 case RemoteMediaIn::RddProcess:
1031 s = TrackSupport::DecodeVideo;
1032 if (StaticPrefs::media_use_remote_encoder_video_software() ||
1033 StaticPrefs::media_use_remote_encoder_video_platform()) {
1034 s += TrackSupport::EncodeVideo;
1035 }
1036#ifndef ANDROID
1037 // Only use RDD for audio coding if we don't have the utility process. If
1038 // we have a CDM (which we can't determine here) on Android, and the GPU
1039 // process is not available, then we want to perform both the video and
1040 // audio decoding in the RDD so that they can share the CDM instance.
1041 if (!StaticPrefs::media_utility_process_enabled())
1042#endif
1043 {
1044 s += TrackSupport::DecodeAudio;
1045 if (StaticPrefs::media_use_remote_encoder_audio_software()) {
1046 s += TrackSupport::EncodeAudio;
1047 }
1048 }
1049 break;
1050 case RemoteMediaIn::UtilityProcess_Generic:
1051 case RemoteMediaIn::UtilityProcess_AppleMedia:
1052 case RemoteMediaIn::UtilityProcess_WMF:
1053 if (StaticPrefs::media_utility_process_enabled()) {
1054 s = TrackSupport::DecodeAudio;
1055 if (StaticPrefs::media_use_remote_encoder_audio_software()) {
1056 s += TrackSupport::EncodeAudio;
1057 }
1058 }
1059 break;
1060 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM:
1061#ifdef MOZ_WMF_MEDIA_ENGINE
1062 // When we enable the media engine, it would need both tracks to
1063 // synchronize the a/v playback.
1064 if (StaticPrefs::media_wmf_media_engine_enabled()) {
1065 s = TrackSupportSet{TrackSupport::DecodeAudio,
1066 TrackSupport::DecodeVideo};
1067 }
1068#endif
1069 break;
1070 default:
1071 MOZ_ASSERT_UNREACHABLE("Undefined location!")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: "
"Undefined location!" ")", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Undefined location!" ")"); do { MOZ_CrashSequence
(__null, 1071); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1072 break;
1073 }
1074 return s;
1075}
1076
1077RemoteMediaManagerChild::RemoteMediaManagerChild(RemoteMediaIn aLocation)
1078 : mLocation(aLocation) {
1079 MOZ_ASSERT(mLocation == RemoteMediaIn::GpuProcess ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocation == RemoteMediaIn::GpuProcess || mLocation ==
RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic
|| mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation
== RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocation == RemoteMediaIn::
GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation
== RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn
::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF
|| mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 1084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1080 mLocation == RemoteMediaIn::RddProcess ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocation == RemoteMediaIn::GpuProcess || mLocation ==
RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic
|| mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation
== RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocation == RemoteMediaIn::
GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation
== RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn
::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF
|| mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 1084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1081 mLocation == RemoteMediaIn::UtilityProcess_Generic ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocation == RemoteMediaIn::GpuProcess || mLocation ==
RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic
|| mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation
== RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocation == RemoteMediaIn::
GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation
== RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn
::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF
|| mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 1084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1082 mLocation == RemoteMediaIn::UtilityProcess_AppleMedia ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocation == RemoteMediaIn::GpuProcess || mLocation ==
RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic
|| mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation
== RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocation == RemoteMediaIn::
GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation
== RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn
::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF
|| mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 1084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1083 mLocation == RemoteMediaIn::UtilityProcess_WMF ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocation == RemoteMediaIn::GpuProcess || mLocation ==
RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic
|| mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation
== RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocation == RemoteMediaIn::
GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation
== RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn
::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF
|| mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 1084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1084 mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLocation == RemoteMediaIn::GpuProcess || mLocation ==
RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic
|| mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation
== RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn
::UtilityProcess_MFMediaEngineCDM)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLocation == RemoteMediaIn::
GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation
== RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn
::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF
|| mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLocation == RemoteMediaIn::GpuProcess || mLocation == RemoteMediaIn::RddProcess || mLocation == RemoteMediaIn::UtilityProcess_Generic || mLocation == RemoteMediaIn::UtilityProcess_AppleMedia || mLocation == RemoteMediaIn::UtilityProcess_WMF || mLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 1084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1085}
1086
1087/* static */
1088void RemoteMediaManagerChild::OpenRemoteMediaManagerChildForProcess(
1089 Endpoint<PRemoteMediaManagerChild>&& aEndpoint, RemoteMediaIn aLocation) {
1090 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1091 if (!managerThread) {
1092 // We've been shutdown, bail.
1093 return;
1094 }
1095 MOZ_ASSERT(managerThread->IsOnCurrentThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(managerThread->IsOnCurrentThread())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(managerThread->IsOnCurrentThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("managerThread->IsOnCurrentThread()"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "managerThread->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 1095); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1096
1097 // For GPU process, make sure we always dispatch everything in sRecreateTasks,
1098 // and resolve any pending promises waiting for the GPU process manager,
1099 // even if we fail since this is as close to being recreated as we will ever
1100 // be.
1101 auto runRecreateTasksIfNeeded = MakeScopeExit([aLocation]() {
1102 if (aLocation == RemoteMediaIn::GpuProcess) {
1103 for (Runnable* task : *sRecreateTasks) {
1104 task->Run();
1105 }
1106 sRecreateTasks->Clear();
1107
1108 if (sGPUProcessRecreatedHolder) {
1109 sGPUProcessRecreatedHolder->ResolveIfExists(true, __func__);
1110 }
1111 }
1112 });
1113
1114 // Only create RemoteMediaManagerChild, bind new endpoint and init
1115 // ipdl if:
1116 // 1) haven't init'd sRemoteMediaManagerChildForProcesses[aLocation]
1117 // or
1118 // 2) if ActorDestroy was called meaning the other end of the ipc channel was
1119 // torn down
1120 // But for GPU process, we always recreate a new manager child.
1121 MOZ_ASSERT(aLocation != RemoteMediaIn::SENTINEL)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLocation != RemoteMediaIn::SENTINEL)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLocation != RemoteMediaIn::
SENTINEL))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLocation != RemoteMediaIn::SENTINEL", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation != RemoteMediaIn::SENTINEL"
")"); do { MOZ_CrashSequence(__null, 1121); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1122 auto& remoteDecoderManagerChild =
1123 sRemoteMediaManagerChildForProcesses[aLocation];
1124 if (aLocation != RemoteMediaIn::GpuProcess && remoteDecoderManagerChild &&
1125 remoteDecoderManagerChild->CanSend()) {
1126 return;
1127 }
1128 remoteDecoderManagerChild = nullptr;
1129 if (aEndpoint.IsValid()) {
1130 RefPtr<RemoteMediaManagerChild> manager =
1131 new RemoteMediaManagerChild(aLocation);
1132 if (aEndpoint.Bind(manager)) {
1133 remoteDecoderManagerChild = manager;
1134 }
1135 }
1136}
1137
1138bool RemoteMediaManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem) {
1139 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1140 if (!managerThread) {
1141 return false;
1142 }
1143 if (!managerThread->IsOnCurrentThread()) {
1144 MOZ_ALWAYS_SUCCEEDS(managerThread->Dispatch(NS_NewRunnableFunction(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocShmem"
, [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->
CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(
shmem); } })))), 1)))), 1))) { } else { do { do { } while (false
); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
")"); do { MOZ_CrashSequence(__null, 1150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1145 "RemoteMediaManagerChild::DeallocShmem",do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocShmem"
, [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->
CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(
shmem); } })))), 1)))), 1))) { } else { do { do { } while (false
); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
")"); do { MOZ_CrashSequence(__null, 1150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1146 [self = RefPtr{this}, shmem = aShmem]() mutable {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocShmem"
, [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->
CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(
shmem); } })))), 1)))), 1))) { } else { do { do { } while (false
); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
")"); do { MOZ_CrashSequence(__null, 1150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1147 if (self->CanSend()) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocShmem"
, [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->
CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(
shmem); } })))), 1)))), 1))) { } else { do { do { } while (false
); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
")"); do { MOZ_CrashSequence(__null, 1150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1148 self->PRemoteMediaManagerChild::DeallocShmem(shmem);do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocShmem"
, [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->
CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(
shmem); } })))), 1)))), 1))) { } else { do { do { } while (false
); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
")"); do { MOZ_CrashSequence(__null, 1150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1149 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocShmem"
, [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->
CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(
shmem); } })))), 1)))), 1))) { } else { do { do { } while (false
); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
")"); do { MOZ_CrashSequence(__null, 1150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1150 })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocShmem"
, [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->
CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(
shmem); } })))), 1)))), 1))) { } else { do { do { } while (false
); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocShmem\", [self = RefPtr{this}, shmem = aShmem]() mutable { if (self->CanSend()) { self->PRemoteMediaManagerChild::DeallocShmem(shmem); } })))"
")"); do { MOZ_CrashSequence(__null, 1150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1151 return true;
1152 }
1153 return PRemoteMediaManagerChild::DeallocShmem(aShmem);
1154}
1155
1156static already_AddRefed<gfx::DataSourceSurface> GetSurfaceForDescriptor(
1157 const SurfaceDescriptor& aDescriptor) {
1158 const auto& sdb = aDescriptor.get_SurfaceDescriptorBuffer();
1159 const auto& shmem = sdb.data().get_Shmem();
1160 const auto& rgb = sdb.desc().get_RGBDescriptor();
1161 const auto stride = ImageDataSerializer::GetRGBStride(rgb);
1162 if (stride.isNothing()) {
1163 LOGE("Invalid stride for buffer");
1164 return nullptr;
1165 }
1166 const auto requiredSize =
1167 ImageDataSerializer::ComputeRGBBufferSize(rgb.size(), rgb.format());
1168 if (requiredSize.isNothing() || shmem.Size<uint8_t>() < *requiredSize) {
1169 LOGE("Shmem too small for required buffer size");
1170 return nullptr;
1171 }
1172
1173 return gfx::Factory::CreateWrappingDataSourceSurface(
1174 shmem.get<uint8_t>(), *stride, rgb.size(), rgb.format());
1175}
1176
1177static void DestroySurfaceDescriptor(ipc::IShmemAllocator* aAllocator,
1178 SurfaceDescriptor* aSurface) {
1179 MOZ_ASSERT(aSurface)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSurface)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSurface))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aSurface", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSurface" ")"
); do { MOZ_CrashSequence(__null, 1179); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1180 const SurfaceDescriptorBuffer& desc = aSurface->get_SurfaceDescriptorBuffer();
1181 aAllocator->DeallocShmem(desc.data().get_Shmem());
1182 *aSurface = SurfaceDescriptor();
1183}
1184
1185struct SurfaceDescriptorUserData {
1186 SurfaceDescriptorUserData(RemoteMediaManagerChild* aAllocator,
1187 SurfaceDescriptor& aSD)
1188 : mAllocator(aAllocator), mSD(aSD) {}
1189 ~SurfaceDescriptorUserData() { DestroySurfaceDescriptor(mAllocator, &mSD); }
1190
1191 RefPtr<RemoteMediaManagerChild> mAllocator;
1192 SurfaceDescriptor mSD;
1193};
1194
1195void DeleteSurfaceDescriptorUserData(void* aClosure) {
1196 SurfaceDescriptorUserData* sd =
1197 reinterpret_cast<SurfaceDescriptorUserData*>(aClosure);
1198 delete sd;
1199}
1200
1201already_AddRefed<SourceSurface> RemoteMediaManagerChild::Readback(
1202 const SurfaceDescriptorGPUVideo& aSD) {
1203 // We can't use NS_DispatchAndSpinEventLoopUntilComplete here since that will
1204 // spin the event loop while it waits. This function can be called from JS and
1205 // we don't want that to happen.
1206 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1207 if (!managerThread) {
1208 return nullptr;
1209 }
1210
1211 SurfaceDescriptor sd;
1212 RefPtr<Runnable> task =
1213 NS_NewRunnableFunction("RemoteMediaManagerChild::Readback", [&]() {
1214 if (CanSend()) {
1215 SendReadback(aSD, &sd);
1216 }
1217 });
1218 SyncRunnable::DispatchToThread(managerThread, task);
1219
1220 if (sd.type() != SurfaceDescriptor::TSurfaceDescriptorBuffer) {
1221 LOGE("Unexpected SurfaceDescriptor type in Readback");
1222 return nullptr;
1223 }
1224 auto& sdb = sd.get_SurfaceDescriptorBuffer();
1225 if (sdb.data().type() != MemoryOrShmem::TShmem) {
1226 LOGE("Unexpected SurfaceDescriptorBuffer data type in Readback");
1227 return nullptr;
1228 }
1229
1230 RefPtr<DataSourceSurface> source = GetSurfaceForDescriptor(sd);
1231 if (!source) {
1232 DestroySurfaceDescriptor(this, &sd);
1233 LOGE("Failed to map SurfaceDescriptor in Readback");
1234 return nullptr;
1235 }
1236
1237 static UserDataKey sSurfaceDescriptor;
1238 source->AddUserData(&sSurfaceDescriptor,
1239 new SurfaceDescriptorUserData(this, sd),
1240 DeleteSurfaceDescriptorUserData);
1241
1242 return source.forget();
1243}
1244
1245already_AddRefed<Image> RemoteMediaManagerChild::TransferToImage(
1246 const SurfaceDescriptorGPUVideo& aSD, const IntSize& aSize,
1247 const ColorDepth& aColorDepth, YUVColorSpace aYUVColorSpace,
1248 ColorSpace2 aColorPrimaries, TransferFunction aTransferFunction,
1249 ColorRange aColorRange) {
1250 // The Image here creates a TextureData object that takes ownership
1251 // of the SurfaceDescriptor, and is responsible for making sure that
1252 // it gets deallocated.
1253 SurfaceDescriptorGPUVideo sd(aSD);
1254 sd.get_SurfaceDescriptorRemoteDecoder().source() =
1255 Some(GetVideoBridgeSourceFromRemoteMediaIn(mLocation));
1256 return MakeAndAddRef<GPUVideoImage>(this, sd, aSize, aColorDepth,
1257 aYUVColorSpace, aColorPrimaries,
1258 aTransferFunction, aColorRange);
1259}
1260
1261void RemoteMediaManagerChild::DeallocateSurfaceDescriptor(
1262 const SurfaceDescriptorGPUVideo& aSD) {
1263 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1264 if (!managerThread) {
1265 return;
1266 }
1267 MOZ_ALWAYS_SUCCEEDS(managerThread->Dispatch(NS_NewRunnableFunction(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocateSurfaceDescriptor"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } }))))
, 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1273); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1273); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1268 "RemoteMediaManagerChild::DeallocateSurfaceDescriptor",do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocateSurfaceDescriptor"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } }))))
, 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1273); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1273); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1269 [ref = RefPtr{this}, sd = aSD]() {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocateSurfaceDescriptor"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } }))))
, 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1273); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1273); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1270 if (ref->CanSend()) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocateSurfaceDescriptor"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } }))))
, 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1273); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1273); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1271 ref->SendDeallocateSurfaceDescriptorGPUVideo(sd);do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocateSurfaceDescriptor"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } }))))
, 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1273); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1273); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1272 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocateSurfaceDescriptor"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } }))))
, 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1273); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1273); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1273 })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch(NS_NewRunnableFunction( "RemoteMediaManagerChild::DeallocateSurfaceDescriptor"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } }))))
, 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1273); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch(NS_NewRunnableFunction( \"RemoteMediaManagerChild::DeallocateSurfaceDescriptor\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1273); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1274}
1275
1276void RemoteMediaManagerChild::OnSetCurrent(
1277 const SurfaceDescriptorGPUVideo& aSD) {
1278 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1279 if (!managerThread) {
1280 return;
1281 }
1282 MOZ_ALWAYS_SUCCEEDS(managerThread->Dispatch(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch( NS_NewRunnableFunction("RemoteMediaManagerChild::OnSetCurrent"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendOnSetCurrent(sd); } })))), 1)))), 1))) { } else {
do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1288); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1288); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1283 NS_NewRunnableFunction("RemoteMediaManagerChild::OnSetCurrent",do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch( NS_NewRunnableFunction("RemoteMediaManagerChild::OnSetCurrent"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendOnSetCurrent(sd); } })))), 1)))), 1))) { } else {
do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1288); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1288); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1284 [ref = RefPtr{this}, sd = aSD]() {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch( NS_NewRunnableFunction("RemoteMediaManagerChild::OnSetCurrent"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendOnSetCurrent(sd); } })))), 1)))), 1))) { } else {
do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1288); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1288); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1285 if (ref->CanSend()) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch( NS_NewRunnableFunction("RemoteMediaManagerChild::OnSetCurrent"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendOnSetCurrent(sd); } })))), 1)))), 1))) { } else {
do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1288); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1288); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1286 ref->SendOnSetCurrent(sd);do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch( NS_NewRunnableFunction("RemoteMediaManagerChild::OnSetCurrent"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendOnSetCurrent(sd); } })))), 1)))), 1))) { } else {
do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1288); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1288); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1287 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch( NS_NewRunnableFunction("RemoteMediaManagerChild::OnSetCurrent"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendOnSetCurrent(sd); } })))), 1)))), 1))) { } else {
do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1288); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1288); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1288 })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(managerThread->Dispatch( NS_NewRunnableFunction("RemoteMediaManagerChild::OnSetCurrent"
, [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) {
ref->SendOnSetCurrent(sd); } })))), 1)))), 1))) { } else {
do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1288); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(managerThread->Dispatch( NS_NewRunnableFunction(\"RemoteMediaManagerChild::OnSetCurrent\", [ref = RefPtr{this}, sd = aSD]() { if (ref->CanSend()) { ref->SendOnSetCurrent(sd); } })))"
")"); do { MOZ_CrashSequence(__null, 1288); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1289}
1290
1291/* static */ void RemoteMediaManagerChild::HandleRejectionError(
1292 const RemoteMediaManagerChild* aDyingManager, RemoteMediaIn aLocation,
1293 const ipc::ResponseRejectReason& aReason,
1294 std::function<void(const MediaResult&)>&& aCallback) {
1295 // If the channel goes down and CanSend() returns false, the IPDL promise will
1296 // be rejected with SendError rather than ActorDestroyed. Both means the same
1297 // thing and we can consider that the parent has crashed. The child can no
1298 // longer be used.
1299
1300 if (aLocation == RemoteMediaIn::GpuProcess) {
1301 // The GPU process will get automatically restarted by the parent process.
1302 // Once it has been restarted the ContentChild will receive the message and
1303 // will call GetManager()->InitForGPUProcess.
1304 // We defer reporting an error until we've recreated the RemoteDecoder
1305 // manager so that it'll be safe for MediaFormatReader to recreate decoders
1306 RunWhenGPUProcessRecreated(
1307 aDyingManager,
1308 NS_NewRunnableFunction(
1309 "RemoteMediaManagerChild::HandleRejectionError",
1310 [callback = std::move(aCallback)]() {
1311 MediaResult error(
1312 NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_RDD_OR_GPU_ERR, __func__);
1313 callback(error);
1314 }));
1315 return;
1316 }
1317
1318 nsresult err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_UTILITY_ERR;
1319 if (aLocation == RemoteMediaIn::RddProcess) {
1320 err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_RDD_OR_GPU_ERR;
1321 } else if (aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
1322 err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_MF_CDM_ERR;
1323 }
1324 // The RDD/utility process is restarted on demand and asynchronously, we can
1325 // immediately inform the caller that a new en/decoder is needed. The process
1326 // will then be restarted during the new en/decoder creation by
1327 aCallback(MediaResult(err, __func__));
1328}
1329
1330void RemoteMediaManagerChild::HandleFatalError(const char* aMsg) {
1331 dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherChildID());
1332}
1333
1334void RemoteMediaManagerChild::ActorDestroy(ActorDestroyReason aWhy) {
1335 // A stale actor that has already been replaced must not reject the wait
1336 // for its successor.
1337 if (GetSingleton(mLocation) != this) {
1338 return;
1339 }
1340 StaticMutexAutoLock lock(sProcessSupportedMutex);
1341 CodecSupportState& state = sCodecSupportState[mLocation];
1342 if (state.mHolder.IsEmpty()) {
1343 return;
1344 }
1345 LOGE("Remote process '{}' went away before reporting codec support",
1346 RemoteMediaInToStr(mLocation));
1347 state.mHolder.Reject(aWhy == NormalShutdown ? NS_ERROR_ILLEGAL_DURING_SHUTDOWN
1348 : NS_ERROR_FAILURE,
1349 __func__);
1350}
1351
1352void RemoteMediaManagerChild::SetSupported(
1353 RemoteMediaIn aLocation, const media::MediaCodecsSupported& aSupported) {
1354 MozPromiseHolder<CodecSupportPromise> holder;
1355 switch (aLocation) {
1356 case RemoteMediaIn::GpuProcess:
1357 case RemoteMediaIn::RddProcess:
1358 case RemoteMediaIn::UtilityProcess_AppleMedia:
1359 case RemoteMediaIn::UtilityProcess_Generic:
1360 case RemoteMediaIn::UtilityProcess_WMF:
1361 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM: {
1362 StaticMutexAutoLock lock(sProcessSupportedMutex);
1363 CodecSupportState& state = sCodecSupportState[aLocation];
1364 state.mSupported = Some(aSupported);
1365 holder = std::move(state.mHolder);
1366 break;
1367 }
1368 default:
1369 MOZ_CRASH("Not to be used for any other process")do { do { } while (false); MOZ_ReportCrash("" "Not to be used for any other process"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 1369); AnnotateMozCrashReason("MOZ_CRASH(" "Not to be used for any other process"
")"); do { MOZ_CrashSequence(__null, 1369); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1370 }
1371 holder.ResolveIfExists(true, __func__);
1372}
1373
1374/* static */
1375RefPtr<RemoteMediaManagerChild::CodecSupportPromise>
1376RemoteMediaManagerChild::EnsureCodecSupportFor(RemoteMediaIn aLocation,
1377 bool aForceRefresh) {
1378 RefPtr<CodecSupportPromise> promise;
1379 {
1380 StaticMutexAutoLock lock(sProcessSupportedMutex);
1381 CodecSupportState& state = sCodecSupportState[aLocation];
1382 if (!aForceRefresh && state.mSupported) {
1
Assuming 'aForceRefresh' is true
1383 return CodecSupportPromise::CreateAndResolve(true, __func__);
1384 }
1385 // Cache is empty or a refresh was requested. Obtain the promise under the
1386 // lock so SetSupported() cannot resolve the holder before we return it.
1387 // The cache is intentionally not cleared on refresh so that sync callers
1388 // continue to see the current value until the next update arrives.
1389 promise = state.mHolder.Ensure(__func__);
1390 }
1391
1392 // Only reached when we are going to wait. Launch the process so
1393 // SetSupported() will eventually fire and resolve the promise.
1394 RefPtr<GenericNonExclusivePromise> launchPromise;
1395 switch (aLocation) {
2
Control jumps to 'case RddProcess:' at line 1402
1396 case RemoteMediaIn::UtilityProcess_Generic:
1397 case RemoteMediaIn::UtilityProcess_AppleMedia:
1398 case RemoteMediaIn::UtilityProcess_WMF:
1399 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM:
1400 launchPromise = LaunchUtilityProcessIfNeeded(aLocation);
1401 break;
1402 case RemoteMediaIn::RddProcess:
1403 launchPromise = LaunchRDDProcessIfNeeded();
3
Calling 'RemoteMediaManagerChild::LaunchRDDProcessIfNeeded'
1404 break;
1405 case RemoteMediaIn::GpuProcess:
1406 launchPromise = EnsureGPUProcessReady();
1407 break;
1408 default:
1409 break;
1410 }
1411
1412 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1413 if (!launchPromise || !managerThread) {
1414 LOGE("Failed to launch remote process '{}'", RemoteMediaInToStr(aLocation));
1415 StaticMutexAutoLock lock(sProcessSupportedMutex);
1416 CodecSupportState& state = sCodecSupportState[aLocation];
1417 state.mHolder.RejectIfExists(NS_ERROR_FAILURE, __func__);
1418 return promise;
1419 }
1420
1421 launchPromise->Then(
1422 managerThread, __func__,
1423 [] {
1424 // If launched successfully, the promise is resolved in SetSupported().
1425 },
1426 [aLocation](nsresult aRv) {
1427 LOGE("Launch of remote process '{}' was rejected with {}",
1428 RemoteMediaInToStr(aLocation), aRv);
1429 StaticMutexAutoLock lock(sProcessSupportedMutex);
1430 CodecSupportState& state = sCodecSupportState[aLocation];
1431 state.mHolder.RejectIfExists(aRv, __func__);
1432 });
1433
1434 return promise;
1435}
1436
1437#undef LOG
1438#undef LOGE
1439
1440} // namespace mozilla

←

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h

→
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#ifndef mozilla_RefPtr_h
6#define mozilla_RefPtr_h
7
8#include <fmt/ostream.h>
9
10#include <type_traits>
11
12#include "mozilla/AlreadyAddRefed.h"
13#include "mozilla/Assertions.h"
14#include "mozilla/Attributes.h"
15#include "mozilla/DbgMacro.h" // for mozilla::DebugValue
16
17/*****************************************************************************/
18
19// template <class T> class RefPtrGetterAddRefs;
20
21class nsQueryReferent;
22class nsCOMPtr_helper;
23class nsISupports;
24
25namespace mozilla {
26template <class T>
27class MovingNotNull;
28template <class T>
29class NotNull;
30template <class T>
31class OwningNonNull;
32template <class T>
33class StaticLocalRefPtr;
34template <class T>
35class StaticRefPtr;
36
37// Traditionally, RefPtr supports automatic refcounting of any pointer type
38// with AddRef() and Release() methods that follow the traditional semantics.
39//
40// This traits class can be specialized to operate on other pointer types. For
41// example, we specialize this trait for opaque FFI types that represent
42// refcounted objects in Rust.
43//
44// Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
45// qualified type.
46template <class U>
47struct RefPtrTraits {
48 static void AddRef(U* aPtr) { aPtr->AddRef(); }
49 static void Release(U* aPtr) { aPtr->Release(); }
18
Calling 'MozPromiseRefcountable::Release'
27
Returning; memory was released
50};
51
52} // namespace mozilla
53
54template <class T>
55class MOZ_IS_REFPTR MOZ_NULL_AFTER_MOVE[[clang::annotate("clang-tidy", "bugprone-use-after-move", "null_after_move"
)]]
RefPtr {
56 private:
57 void assign_with_AddRef(T* aRawPtr) {
58 if (aRawPtr) {
12
Assuming 'aRawPtr' is null
13
Taking false branch
59 ConstRemovingRefPtrTraits<T>::AddRef(aRawPtr);
60 }
61 assign_assuming_AddRef(aRawPtr);
14
Calling 'RefPtr::assign_assuming_AddRef'
30
Returning; memory was released
62 }
63
64 void assign_assuming_AddRef(T* aNewPtr) {
65 T* oldPtr = mRawPtr;
66 mRawPtr = aNewPtr;
67 if (oldPtr
14.1
'oldPtr' is non-null
14.1
'oldPtr' is non-null
14.1
'oldPtr' is non-null
14.1
'oldPtr' is non-null
) {
15
Taking true branch
68 ConstRemovingRefPtrTraits<T>::Release(oldPtr);
16
Calling 'ConstRemovingRefPtrTraits::Release'
29
Returning; memory was released via 1st parameter
69 }
70 }
71
72 private:
73 T* MOZ_OWNING_REF mRawPtr;
74
75 public:
76 typedef T element_type;
77
78 ~RefPtr() {
79 if (mRawPtr
35.1
Field 'mRawPtr' is non-null
35.1
Field 'mRawPtr' is non-null
35.1
Field 'mRawPtr' is non-null
35.1
Field 'mRawPtr' is non-null
) {
36
Taking true branch
80 ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
37
Use of memory after it is released
81 }
82 }
83
84 // Constructors
85
86 constexpr RefPtr()
87 : mRawPtr(nullptr)
88 // default constructor
89 {}
90
91 RefPtr(const RefPtr<T>& aSmartPtr)
92 : mRawPtr(aSmartPtr.mRawPtr)
93 // copy-constructor
94 {
95 if (mRawPtr) {
96 ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
97 }
98 }
99
100 RefPtr(RefPtr<T>&& aRefPtr) noexcept : mRawPtr(aRefPtr.mRawPtr) {
101 aRefPtr.mRawPtr = nullptr;
102 }
103
104 // construct from a raw pointer (of the right type)
105
106 MOZ_IMPLICIT RefPtr(T* aRawPtr) : mRawPtr(aRawPtr) {
107 if (mRawPtr) {
108 ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
109 }
110 }
111
112 MOZ_IMPLICIT constexpr RefPtr(std::nullptr_t) : mRawPtr(nullptr) {}
113
114 template <typename I,
115 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
116 MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
117 : mRawPtr(aSmartPtr.take())
118 // construct from |already_AddRefed|
119 {}
120
121 template <typename I,
122 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
123 MOZ_IMPLICIT RefPtr(already_AddRefed<I>&& aSmartPtr)
124 : mRawPtr(aSmartPtr.take())
125 // construct from |otherRefPtr.forget()|
126 {}
127
128 template <typename I,
129 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
130 MOZ_IMPLICIT RefPtr(const RefPtr<I>& aSmartPtr)
131 : mRawPtr(aSmartPtr.get())
132 // copy-construct from a smart pointer with a related pointer type
133 {
134 if (mRawPtr) {
135 ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
136 }
137 }
138
139 template <typename I,
140 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
141 MOZ_IMPLICIT RefPtr(RefPtr<I>&& aSmartPtr)
142 : mRawPtr(aSmartPtr.forget().take())
143 // construct from |Move(RefPtr<SomeSubclassOfT>)|.
144 {}
145
146 template <typename I,
147 typename = std::enable_if_t<!std::is_same_v<I, RefPtr<T>> &&
148 std::is_convertible_v<I, RefPtr<T>>>>
149 MOZ_IMPLICIT RefPtr(const mozilla::NotNull<I>& aSmartPtr)
150 : mRawPtr(RefPtr<T>(aSmartPtr.get()).forget().take())
151 // construct from |mozilla::NotNull|.
152 {}
153
154 template <typename I,
155 typename = std::enable_if_t<!std::is_same_v<I, RefPtr<T>> &&
156 std::is_convertible_v<I, RefPtr<T>>>>
157 MOZ_IMPLICIT RefPtr(mozilla::MovingNotNull<I>&& aSmartPtr)
158 : mRawPtr(RefPtr<T>(std::move(aSmartPtr).unwrapBasePtr()).forget().take())
159 // construct from |mozilla::MovingNotNull|.
160 {}
161
162 MOZ_IMPLICIT RefPtr(const nsQueryReferent& aHelper);
163 MOZ_IMPLICIT RefPtr(const nsCOMPtr_helper& aHelper);
164
165 // Defined in OwningNonNull.h
166 template <class U>
167 MOZ_IMPLICIT RefPtr(const mozilla::OwningNonNull<U>& aOther);
168
169 // Defined in StaticLocalPtr.h
170 template <class U>
171 MOZ_IMPLICIT RefPtr(const mozilla::StaticLocalRefPtr<U>& aOther);
172
173 // Defined in StaticPtr.h
174 template <class U>
175 MOZ_IMPLICIT RefPtr(const mozilla::StaticRefPtr<U>& aOther);
176
177 // Assignment operators
178
179 RefPtr<T>& operator=(decltype(nullptr)) {
180 assign_assuming_AddRef(nullptr);
181 return *this;
182 }
183
184 RefPtr<T>& operator=(const RefPtr<T>& aRhs)
185 // copy assignment operator
186 {
187 assign_with_AddRef(aRhs.mRawPtr);
11
Calling 'RefPtr::assign_with_AddRef'
31
Returning; memory was released
188 return *this;
189 }
190
191 template <typename I>
192 RefPtr<T>& operator=(const RefPtr<I>& aRhs)
193 // assign from an RefPtr of a related pointer type
194 {
195 assign_with_AddRef(aRhs.get());
196 return *this;
197 }
198
199 RefPtr<T>& operator=(T* aRhs)
200 // assign from a raw pointer (of the right type)
201 {
202 assign_with_AddRef(aRhs);
203 return *this;
204 }
205
206 template <typename I>
207 RefPtr<T>& operator=(already_AddRefed<I>& aRhs)
208 // assign from |already_AddRefed|
209 {
210 assign_assuming_AddRef(aRhs.take());
211 return *this;
212 }
213
214 template <typename I>
215 RefPtr<T>& operator=(already_AddRefed<I>&& aRhs)
216 // assign from |otherRefPtr.forget()|
217 {
218 assign_assuming_AddRef(aRhs.take());
219 return *this;
220 }
221
222 RefPtr<T>& operator=(const nsQueryReferent& aQueryReferent);
223 RefPtr<T>& operator=(const nsCOMPtr_helper& aHelper);
224
225 template <typename I,
226 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
227 RefPtr<T>& operator=(RefPtr<I>&& aRefPtr) noexcept {
228 assign_assuming_AddRef(aRefPtr.forget().take());
229 return *this;
230 }
231
232 template <typename I,
233 typename = std::enable_if_t<std::is_convertible_v<I, RefPtr<T>>>>
234 RefPtr<T>& operator=(const mozilla::NotNull<I>& aSmartPtr)
235 // assign from |mozilla::NotNull|.
236 {
237 assign_assuming_AddRef(RefPtr<T>(aSmartPtr.get()).forget().take());
238 return *this;
239 }
240
241 template <typename I,
242 typename = std::enable_if_t<std::is_convertible_v<I, RefPtr<T>>>>
243 RefPtr<T>& operator=(mozilla::MovingNotNull<I>&& aSmartPtr)
244 // assign from |mozilla::MovingNotNull|.
245 {
246 assign_assuming_AddRef(
247 RefPtr<T>(std::move(aSmartPtr).unwrapBasePtr()).forget().take());
248 return *this;
249 }
250
251 // Defined in OwningNonNull.h
252 template <class U>
253 RefPtr<T>& operator=(const mozilla::OwningNonNull<U>& aOther);
254
255 // Defined in StaticLocalPtr.h
256 template <class U>
257 RefPtr<T>& operator=(const mozilla::StaticLocalRefPtr<U>& aOther);
258
259 // Defined in StaticPtr.h
260 template <class U>
261 RefPtr<T>& operator=(const mozilla::StaticRefPtr<U>& aOther);
262
263 // Other pointer operators
264
265 void swap(RefPtr<T>& aRhs)
266 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
267 {
268 T* temp = aRhs.mRawPtr;
269 aRhs.mRawPtr = mRawPtr;
270 mRawPtr = temp;
271 }
272
273 void swap(T*& aRhs)
274 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
275 {
276 T* temp = aRhs;
277 aRhs = mRawPtr;
278 mRawPtr = temp;
279 }
280
281 already_AddRefed<T> MOZ_MAY_CALL_AFTER_MUST_RETURN forget()
282 // return the value of mRawPtr and null out mRawPtr. Useful for
283 // already_AddRefed return values.
284 {
285 T* temp = nullptr;
286 swap(temp);
287 return already_AddRefed<T>(temp);
288 }
289
290 template <typename I>
291 void forget(I** aRhs)
292 // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
293 // Useful to avoid unnecessary AddRef/Release pairs with "out"
294 // parameters where aRhs bay be a T** or an I** where I is a base class
295 // of T.
296 {
297 MOZ_ASSERT(aRhs, "Null pointer passed to forget!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRhs)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aRhs))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aRhs" " (" "Null pointer passed to forget!"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRhs" ") (" "Null pointer passed to forget!"
")"); do { MOZ_CrashSequence(__null, 297); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
298 *aRhs = mRawPtr;
299 mRawPtr = nullptr;
300 }
301
302 void forget(nsISupports** aRhs) {
303 MOZ_ASSERT(aRhs, "Null pointer passed to forget!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRhs)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aRhs))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aRhs" " (" "Null pointer passed to forget!"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRhs" ") (" "Null pointer passed to forget!"
")"); do { MOZ_CrashSequence(__null, 303); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
304 *aRhs = ToSupports(mRawPtr);
305 mRawPtr = nullptr;
306 }
307
308 T* get() const
309 /*
310 Prefer the implicit conversion provided automatically by |operator T*()
311 const|. Use |get()| to resolve ambiguity or to get a castable pointer.
312 */
313 {
314 return const_cast<T*>(mRawPtr);
315 }
316
317 operator T*() const&
318 /*
319 ...makes an |RefPtr| act like its underlying raw pointer type whenever it
320 is used in a context where a raw pointer is expected. It is this operator
321 that makes an |RefPtr| substitutable for a raw pointer.
322
323 Prefer the implicit use of this operator to calling |get()|, except where
324 necessary to resolve ambiguity.
325 */
326 {
327 return get();
328 }
329
330 // Don't allow implicit conversion of temporary RefPtr to raw pointer,
331 // because the refcount might be one and the pointer will immediately become
332 // invalid.
333 operator T*() const&& = delete;
334
335 // These are needed to avoid the deleted operator above. XXX Why is operator!
336 // needed separately? Shouldn't the compiler prefer using the non-deleted
337 // operator bool instead of the deleted operator T*?
338 explicit operator bool() const { return !!mRawPtr; }
339 bool operator!() const { return !mRawPtr; }
340
341 T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
342 MOZ_ASSERT(mRawPtr != nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator->()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator->()."
")"); do { MOZ_CrashSequence(__null, 343); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
343 "You can't dereference a NULL RefPtr with operator->().")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator->()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator->()."
")"); do { MOZ_CrashSequence(__null, 343); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
344 return get();
345 }
346
347 template <typename R, typename... Args>
348 class Proxy {
349 typedef R (T::*member_function)(Args...);
350 T* mRawPtr;
351 member_function mFunction;
352
353 public:
354 Proxy(T* aRawPtr, member_function aFunction)
355 : mRawPtr(aRawPtr), mFunction(aFunction) {}
356 template <typename... ActualArgs>
357 R operator()(ActualArgs&&... aArgs) {
358 return ((*mRawPtr).*mFunction)(std::forward<ActualArgs>(aArgs)...);
359 }
360 };
361
362 template <typename R, typename... Args>
363 Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const {
364 MOZ_ASSERT(mRawPtr != nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator->*()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator->*()."
")"); do { MOZ_CrashSequence(__null, 365); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
365 "You can't dereference a NULL RefPtr with operator->*().")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator->*()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator->*()."
")"); do { MOZ_CrashSequence(__null, 365); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
366 return Proxy<R, Args...>(get(), aFptr);
367 }
368
369 RefPtr<T>* get_address()
370 // This is not intended to be used by clients. See |address_of|
371 // below.
372 {
373 return this;
374 }
375
376 const RefPtr<T>* get_address() const
377 // This is not intended to be used by clients. See |address_of|
378 // below.
379 {
380 return this;
381 }
382
383 public:
384 T& operator*() const {
385 MOZ_ASSERT(mRawPtr != nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator*()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator*()."
")"); do { MOZ_CrashSequence(__null, 386); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
386 "You can't dereference a NULL RefPtr with operator*().")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator*()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator*()."
")"); do { MOZ_CrashSequence(__null, 386); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
387 return *get();
388 }
389
390 T** StartAssignment() {
391 assign_assuming_AddRef(nullptr);
392 return reinterpret_cast<T**>(&mRawPtr);
393 }
394
395 private:
396 // This helper class makes |RefPtr<const T>| possible by casting away
397 // the constness from the pointer when calling AddRef() and Release().
398 //
399 // This is necessary because AddRef() and Release() implementations can't
400 // generally expected to be const themselves (without heavy use of |mutable|
401 // and |const_cast| in their own implementations).
402 //
403 // This should be sound because while |RefPtr<const T>| provides a
404 // const view of an object, the object itself should not be const (it
405 // would have to be allocated as |new const T| or similar to be const).
406 template <class U>
407 struct ConstRemovingRefPtrTraits {
408 static void AddRef(U* aPtr) { mozilla::RefPtrTraits<U>::AddRef(aPtr); }
409 static void Release(U* aPtr) { mozilla::RefPtrTraits<U>::Release(aPtr); }
17
Calling 'RefPtrTraits::Release'
28
Returning; memory was released via 1st parameter
410 };
411 template <class U>
412 struct ConstRemovingRefPtrTraits<const U> {
413 static void AddRef(const U* aPtr) {
414 mozilla::RefPtrTraits<U>::AddRef(const_cast<U*>(aPtr));
415 }
416 static void Release(const U* aPtr) {
417 mozilla::RefPtrTraits<U>::Release(const_cast<U*>(aPtr));
418 }
419 };
420};
421
422class nsCycleCollectionTraversalCallback;
423template <typename T>
424void CycleCollectionNoteChild(nsCycleCollectionTraversalCallback& aCallback,
425 T* aChild, const char* aName, uint32_t aFlags);
426
427template <typename T>
428inline void ImplCycleCollectionUnlink(RefPtr<T>& aField) {
429 aField = nullptr;
430}
431
432template <typename T>
433inline void ImplCycleCollectionTraverse(
434 nsCycleCollectionTraversalCallback& aCallback, const RefPtr<T>& aField,
435 const char* aName, uint32_t aFlags = 0) {
436 CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
437}
438
439template <class T>
440inline RefPtr<T>* address_of(RefPtr<T>& aPtr) {
441 return aPtr.get_address();
442}
443
444template <class T>
445inline const RefPtr<T>* address_of(const RefPtr<T>& aPtr) {
446 return aPtr.get_address();
447}
448
449template <class T>
450class RefPtrGetterAddRefs
451/*
452 ...
453
454 This class is designed to be used for anonymous temporary objects in the
455 argument list of calls that return COM interface pointers, e.g.,
456
457 RefPtr<IFoo> fooP;
458 ...->GetAddRefedPointer(getter_AddRefs(fooP))
459
460 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
461
462 When initialized with a |RefPtr|, as in the example above, it returns
463 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
464 outer call (|GetAddRefedPointer| in this case) can fill in.
465
466 This type should be a nested class inside |RefPtr<T>|.
467*/
468{
469 public:
470 explicit RefPtrGetterAddRefs(RefPtr<T>& aSmartPtr)
471 : mTargetSmartPtr(aSmartPtr) {
472 // nothing else to do
473 }
474
475 operator void**() {
476 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
477 }
478
479 operator T**() { return mTargetSmartPtr.StartAssignment(); }
480
481 T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); }
482
483 private:
484 RefPtr<T>& mTargetSmartPtr;
485};
486
487template <class T>
488inline RefPtrGetterAddRefs<T> getter_AddRefs(RefPtr<T>& aSmartPtr)
489/*
490 Used around a |RefPtr| when
491 ...makes the class |RefPtrGetterAddRefs<T>| invisible.
492*/
493{
494 return RefPtrGetterAddRefs<T>(aSmartPtr);
495}
496
497// Comparing two |RefPtr|s
498
499template <class T, class U>
500inline bool operator==(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs) {
501 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
502}
503
504template <class T, class U>
505inline bool operator!=(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs) {
506 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
507}
508
509// Comparing an |RefPtr| to a raw pointer
510
511template <class T, class U>
512inline bool operator==(const RefPtr<T>& aLhs, const U* aRhs) {
513 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs);
514}
515
516template <class T, class U>
517inline bool operator==(const U* aLhs, const RefPtr<T>& aRhs) {
518 return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
519}
520
521template <class T, class U>
522inline bool operator!=(const RefPtr<T>& aLhs, const U* aRhs) {
523 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs);
524}
525
526template <class T, class U>
527inline bool operator!=(const U* aLhs, const RefPtr<T>& aRhs) {
528 return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
529}
530
531template <class T, class U>
532inline bool operator==(const RefPtr<T>& aLhs, U* aRhs) {
533 return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
534}
535
536template <class T, class U>
537inline bool operator==(U* aLhs, const RefPtr<T>& aRhs) {
538 return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
539}
540
541template <class T, class U>
542inline bool operator!=(const RefPtr<T>& aLhs, U* aRhs) {
543 return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
544}
545
546template <class T, class U>
547inline bool operator!=(U* aLhs, const RefPtr<T>& aRhs) {
548 return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
549}
550
551// Comparing an |RefPtr| to |nullptr|
552
553template <class T>
554inline bool operator==(const RefPtr<T>& aLhs, decltype(nullptr)) {
555 return aLhs.get() == nullptr;
556}
557
558template <class T>
559inline bool operator==(decltype(nullptr), const RefPtr<T>& aRhs) {
560 return nullptr == aRhs.get();
561}
562
563template <class T>
564inline bool operator!=(const RefPtr<T>& aLhs, decltype(nullptr)) {
565 return aLhs.get() != nullptr;
566}
567
568template <class T>
569inline bool operator!=(decltype(nullptr), const RefPtr<T>& aRhs) {
570 return nullptr != aRhs.get();
571}
572
573// MOZ_DBG support
574
575template <class T>
576std::ostream& operator<<(std::ostream& aOut, const RefPtr<T>& aObj) {
577 return mozilla::DebugValue(aOut, aObj.get());
578}
579
580template <typename T>
581struct fmt::formatter<RefPtr<T>> : fmt::ostream_formatter {};
582
583/*****************************************************************************/
584
585template <class T>
586inline already_AddRefed<T> do_AddRef(T* aObj) {
587 RefPtr<T> ref(aObj);
588 return ref.forget();
589}
590
591template <class T>
592inline already_AddRefed<T> do_AddRef(const RefPtr<T>& aObj) {
593 RefPtr<T> ref(aObj);
594 return ref.forget();
595}
596
597namespace mozilla {
598/**
599 * Helper function to be able to conveniently write things like:
600 *
601 * already_AddRefed<T>
602 * f(...)
603 * {
604 * return MakeAndAddRef<T>(...);
605 * }
606 */
607template <typename T, typename... Args>
608already_AddRefed<T> MakeAndAddRef(Args&&... aArgs) {
609 RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
610 return p.forget();
611}
612
613/**
614 * Helper function to be able to conveniently write things like:
615 *
616 * auto runnable =
617 * MakeRefPtr<ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>>(
618 * mOnSuccess, mOnFailure, *error, mWindowID);
619 */
620template <typename T, typename... Args>
621RefPtr<T> MakeRefPtr(Args&&... aArgs) {
622 RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
623 return p;
624}
625
626} // namespace mozilla
627
628/**
629 * Deduction guide to allow simple `RefPtr` definitions from an
630 * already_AddRefed<T> without repeating the type, e.g.:
631 *
632 * RefPtr ptr = MakeAndAddRef<SomeType>(...);
633 */
634template <typename T>
635RefPtr(already_AddRefed<T>) -> RefPtr<T>;
636
637#endif /* mozilla_RefPtr_h */

←

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h

→
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#ifndef XPCOM_THREADS_MOZPROMISE_H_
6#define XPCOM_THREADS_MOZPROMISE_H_
7
8#include <type_traits>
9#include <utility>
10
11#include "mozilla/Attributes.h"
12#include "mozilla/ErrorNames.h"
13#include "mozilla/Logging.h"
14#include "mozilla/Maybe.h"
15#include "mozilla/Monitor.h"
16#include "mozilla/Mutex.h"
17#include "mozilla/RefPtr.h"
18#include "mozilla/StaticString.h"
19#include "mozilla/UniquePtr.h"
20#include "mozilla/Variant.h"
21#include "nsIDirectTaskDispatcher.h"
22#include "nsISerialEventTarget.h"
23#include "nsTArray.h"
24#include "nsThreadUtils.h"
25
26#ifdef MOZ_WIDGET_ANDROID
27# include "mozilla/jni/GeckoResultUtils.h"
28#endif
29
30#if MOZ_DIAGNOSTIC_ASSERT_ENABLED1
31# define PROMISE_DEBUG
32#endif
33
34#ifdef PROMISE_DEBUG
35# define PROMISE_ASSERT MOZ_RELEASE_ASSERT
36#else
37# define PROMISE_ASSERT(...) \
38 do { \
39 } while (0)
40#endif
41
42#if DEBUG1
43# include "nsPrintfCString.h"
44#endif
45
46namespace mozilla {
47
48namespace dom {
49class Promise;
50}
51
52extern LazyLogModule gMozPromiseLog;
53
54#define PROMISE_LOG(x, ...) \
55 MOZ_LOG(gMozPromiseLog, mozilla::LogLevel::Debug, (x, ##__VA_ARGS__))do { const ::mozilla::LogModule* moz_real_module = gMozPromiseLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, x, ##__VA_ARGS__)
; } } while (0)
56
57namespace detail {
58template <typename F>
59struct MethodTraitsHelper : MethodTraitsHelper<decltype(&F::operator())> {};
60template <typename ThisType, typename Ret, typename... ArgTypes>
61struct MethodTraitsHelper<Ret (ThisType::*)(ArgTypes...)> {
62 using ReturnType = Ret;
63 static const size_t ArgSize = sizeof...(ArgTypes);
64};
65template <typename ThisType, typename Ret, typename... ArgTypes>
66struct MethodTraitsHelper<Ret (ThisType::*)(ArgTypes...) const> {
67 using ReturnType = Ret;
68 static const size_t ArgSize = sizeof...(ArgTypes);
69};
70template <typename ThisType, typename Ret, typename... ArgTypes>
71struct MethodTraitsHelper<Ret (ThisType::*)(ArgTypes...) volatile> {
72 using ReturnType = Ret;
73 static const size_t ArgSize = sizeof...(ArgTypes);
74};
75template <typename ThisType, typename Ret, typename... ArgTypes>
76struct MethodTraitsHelper<Ret (ThisType::*)(ArgTypes...) const volatile> {
77 using ReturnType = Ret;
78 static const size_t ArgSize = sizeof...(ArgTypes);
79};
80template <typename T>
81struct MethodTrait : MethodTraitsHelper<std::remove_reference_t<T>> {};
82
83} // namespace detail
84
85template <typename T>
86using MethodReturnType = typename detail::MethodTrait<T>::ReturnType;
87
88template <typename MethodType>
89constexpr bool TakesAnyArguments =
90 detail::MethodTrait<MethodType>::ArgSize != 0;
91
92template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
93class MozPromise;
94
95template <typename T>
96constexpr bool IsMozPromise = false;
97
98template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
99constexpr bool
100 IsMozPromise<MozPromise<ResolveValueT, RejectValueT, IsExclusive>> = true;
101
102/*
103 * A promise manages an asynchronous request that may or may not be able to be
104 * fulfilled immediately. When an API returns a promise, the consumer may attach
105 * callbacks to be invoked (asynchronously, on a specified thread) when the
106 * request is either completed (resolved) or cannot be completed (rejected).
107 * Whereas JS promise callbacks are dispatched from Microtask checkpoints,
108 * MozPromises resolution/rejection make a normal round-trip through the event
109 * loop, which simplifies their ordering semantics relative to other native
110 * code.
111 *
112 * MozPromises attempt to mirror the spirit of JS Promises to the extent that
113 * is possible (and desirable) in C++. While the intent is that MozPromises
114 * feel familiar to programmers who are accustomed to their JS-implemented
115 * cousin, we don't shy away from imposing restrictions and adding features that
116 * make sense for the use cases we encounter.
117 *
118 * A MozPromise is ThreadSafe, and may be ->Then()ed on any thread. The Then()
119 * call accepts resolve and reject callbacks, and returns a magic object which
120 * will be implicitly converted to a MozPromise::Request or a MozPromise object
121 * depending on how the return value is used. The magic object serves several
122 * purposes for the consumer.
123 *
124 * (1) When converting to a MozPromise::Request, it allows the caller to
125 * cancel the delivery of the resolve/reject value if it has not already
126 * occurred, via Disconnect() (this must be done on the target thread to
127 * avoid racing).
128 *
129 * (2) When converting to a MozPromise (which is called a completion promise),
130 * it allows promise chaining so ->Then() can be called again to attach
131 * more resolve and reject callbacks. If the resolve/reject callback
132 * returns a new MozPromise, that promise is chained to the completion
133 * promise, such that its resolve/reject value will be forwarded along
134 * when it arrives. If the resolve/reject callback returns void, the
135 * completion promise is resolved/rejected with the same value that was
136 * passed to the callback.
137 *
138 * The MozPromise APIs skirt traditional XPCOM convention by returning nsRefPtrs
139 * (rather than already_AddRefed) from various methods. This is done to allow
140 * elegant chaining of calls without cluttering up the code with intermediate
141 * variables, and without introducing separate API variants for callers that
142 * want a return value (from, say, ->Then()) from those that don't.
143 *
144 * When IsExclusive is true, the MozPromise does a release-mode assertion that
145 * there is at most one call to either Then(...) or ChainTo(...).
146 */
147
148class MozPromiseRefcountable {
149 public:
150 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozPromiseRefcountable)public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<MozPromiseRefcountable>, "Reference-counted class "
"MozPromiseRefcountable" " 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" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 150
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("MozPromiseRefcountable"), (uint32_t)(sizeof(*this))); return
(nsrefcnt)count; } MozExternalRefCountType 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" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 150
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("MozPromiseRefcountable")); if (count == 0) { delete
(this); return 0; } return count; } using HasThreadSafeRefCnt
= std::true_type; protected: ::mozilla::ThreadSafeAutoRefCnt
mRefCnt; public:
19
Assuming the condition is true
20
Taking false branch
21
Loop condition is false. Exiting loop
22
Assuming 'count' is equal to 0
23
Taking true branch
24
Calling 'operator delete'
26
Returning from 'operator delete'
151 protected:
152 virtual ~MozPromiseRefcountable() = default;
153};
154
155class MozPromiseBase : public MozPromiseRefcountable {
156 public:
157 virtual void AssertIsDead() = 0;
158};
159
160template <typename T>
161class MozPromiseHolder;
162template <typename PromiseType, typename ImplType>
163class MozPromiseHolderBase;
164template <typename T>
165class MozPromiseRequestHolder;
166template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
167class MozPromise : public MozPromiseBase {
168 static const uint32_t sMagic = 0xcecace11;
169
170 // Return a |T&&| to enable move when IsExclusive is true or
171 // a |const T&| to enforce copy otherwise.
172 template <typename T,
173 typename R = std::conditional_t<IsExclusive, T&&, const T&>>
174 static R MaybeMove(T& aX) {
175 return static_cast<R>(aX);
176 }
177
178 public:
179 using ResolveValueType = ResolveValueT;
180 using RejectValueType = RejectValueT;
181 class ResolveOrRejectValue {
182 public:
183 template <typename ResolveValueType_>
184 void SetResolve(ResolveValueType_&& aResolveValue) {
185 MOZ_ASSERT(IsNothing())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNothing())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNothing()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsNothing()", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 185); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNothing()"
")"); do { MOZ_CrashSequence(__null, 185); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
186 mValue = Storage(VariantIndex<ResolveIndex>{},
187 std::forward<ResolveValueType_>(aResolveValue));
188 }
189
190 template <typename RejectValueType_>
191 void SetReject(RejectValueType_&& aRejectValue) {
192 MOZ_ASSERT(IsNothing())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNothing())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNothing()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsNothing()", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNothing()"
")"); do { MOZ_CrashSequence(__null, 192); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
193 mValue = Storage(VariantIndex<RejectIndex>{},
194 std::forward<RejectValueType_>(aRejectValue));
195 }
196
197 template <typename ResolveValueType_>
198 static ResolveOrRejectValue MakeResolve(ResolveValueType_&& aResolveValue) {
199 ResolveOrRejectValue val;
200 val.SetResolve(std::forward<ResolveValueType_>(aResolveValue));
201 return val;
202 }
203
204 template <typename RejectValueType_>
205 static ResolveOrRejectValue MakeReject(RejectValueType_&& aRejectValue) {
206 ResolveOrRejectValue val;
207 val.SetReject(std::forward<RejectValueType_>(aRejectValue));
208 return val;
209 }
210
211 bool IsResolve() const { return mValue.template is<ResolveIndex>(); }
212 bool IsReject() const { return mValue.template is<RejectIndex>(); }
213 bool IsNothing() const { return mValue.template is<NothingIndex>(); }
214
215 const ResolveValueType& ResolveValue() const {
216 return mValue.template as<ResolveIndex>();
217 }
218 ResolveValueType& ResolveValue() {
219 return mValue.template as<ResolveIndex>();
220 }
221 const RejectValueType& RejectValue() const {
222 return mValue.template as<RejectIndex>();
223 }
224 RejectValueType& RejectValue() { return mValue.template as<RejectIndex>(); }
225
226 private:
227 enum { NothingIndex, ResolveIndex, RejectIndex };
228 using Storage = Variant<Nothing, ResolveValueType, RejectValueType>;
229 Storage mValue = Storage(VariantIndex<NothingIndex>{});
230 };
231
232 protected:
233 // MozPromise is the public type, and never constructed directly. Construct
234 // a MozPromise::Private, defined below.
235 MozPromise(StaticString aCreationSite, bool aIsCompletionPromise)
236 : mCreationSite(aCreationSite),
237 mMutex("MozPromise Mutex"),
238 mHaveRequest(false),
239 mIsCompletionPromise(aIsCompletionPromise)
240#ifdef PROMISE_DEBUG
241 ,
242 mMagic4(&mMutex)
243#endif
244 {
245 PROMISE_LOG("%s creating MozPromise (%p)", mCreationSite.get(), this);
246 }
247
248 public:
249 // MozPromise::Private allows us to separate the public interface (upon which
250 // consumers of the promise may invoke methods like Then()) from the private
251 // interface (upon which the creator of the promise may invoke Resolve() or
252 // Reject()). APIs should create and store a MozPromise::Private (usually
253 // via a MozPromiseHolder), and return a MozPromise to consumers.
254 //
255 // NB: We can include the definition of this class inline once B2G ICS is
256 // gone.
257 class Private;
258
259 template <typename ResolveValueType_>
260 [[nodiscard]] static RefPtr<MozPromise> CreateAndResolve(
261 ResolveValueType_&& aResolveValue, StaticString aResolveSite) {
262 static_assert(std::is_convertible_v<ResolveValueType_, ResolveValueT>,
263 "Resolve() argument must be implicitly convertible to "
264 "MozPromise's ResolveValueT");
265 RefPtr<typename MozPromise::Private> p =
266 new MozPromise::Private(aResolveSite);
267 p->Resolve(std::forward<ResolveValueType_>(aResolveValue), aResolveSite);
268 return p;
269 }
270
271 template <typename RejectValueType_>
272 [[nodiscard]] static RefPtr<MozPromise> CreateAndReject(
273 RejectValueType_&& aRejectValue, StaticString aRejectSite) {
274 static_assert(std::is_convertible_v<RejectValueType_, RejectValueT>,
275 "Reject() argument must be implicitly convertible to "
276 "MozPromise's RejectValueT");
277 RefPtr<typename MozPromise::Private> p =
278 new MozPromise::Private(aRejectSite);
279 p->Reject(std::forward<RejectValueType_>(aRejectValue), aRejectSite);
280 return p;
281 }
282
283 template <typename ResolveOrRejectValueType_>
284 [[nodiscard]] static RefPtr<MozPromise> CreateAndResolveOrReject(
285 ResolveOrRejectValueType_&& aValue, StaticString aSite) {
286 RefPtr<typename MozPromise::Private> p = new MozPromise::Private(aSite);
287 p->ResolveOrReject(std::forward<ResolveOrRejectValueType_>(aValue), aSite);
288 return p;
289 }
290
291 using AllPromiseType = MozPromise<CopyableTArray<ResolveValueType>,
292 RejectValueType, IsExclusive>;
293 using AllSettledPromiseType =
294 MozPromise<CopyableTArray<ResolveOrRejectValue>, bool, IsExclusive>;
295
296 private:
297 class AllPromiseHolder : public MozPromiseRefcountable {
298 public:
299 explicit AllPromiseHolder(size_t aDependentPromises)
300 : mPromise(new typename AllPromiseType::Private(__func__)),
301 mOutstandingPromises(aDependentPromises) {
302 MOZ_ASSERT(aDependentPromises > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDependentPromises > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDependentPromises > 0)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDependentPromises > 0"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDependentPromises > 0"
")"); do { MOZ_CrashSequence(__null, 302); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
303 mResolveValues.SetLength(aDependentPromises);
304 }
305
306 template <typename ResolveValueType_>
307 void Resolve(size_t aIndex, ResolveValueType_&& aResolveValue) {
308 if (!mPromise) {
309 // Already rejected.
310 return;
311 }
312
313 mResolveValues[aIndex].emplace(
314 std::forward<ResolveValueType_>(aResolveValue));
315 if (--mOutstandingPromises == 0) {
316 nsTArray<ResolveValueType> resolveValues;
317 resolveValues.SetCapacity(mResolveValues.Length());
318 for (auto&& resolveValue : mResolveValues) {
319 resolveValues.AppendElement(std::move(resolveValue.ref()));
320 }
321
322 mPromise->Resolve(std::move(resolveValues), __func__);
323 mPromise = nullptr;
324 mResolveValues.Clear();
325 }
326 }
327
328 template <typename RejectValueType_>
329 void Reject(RejectValueType_&& aRejectValue) {
330 if (!mPromise) {
331 // Already rejected.
332 return;
333 }
334
335 mPromise->Reject(std::forward<RejectValueType_>(aRejectValue), __func__);
336 mPromise = nullptr;
337 mResolveValues.Clear();
338 }
339
340 AllPromiseType* Promise() { return mPromise; }
341
342 private:
343 nsTArray<Maybe<ResolveValueType>> mResolveValues;
344 RefPtr<typename AllPromiseType::Private> mPromise;
345 size_t mOutstandingPromises;
346 };
347
348 // Trying to pass ResolveOrRejectValue by value fails static analysis checks,
349 // so we need to use either a const& or an rvalue reference, depending on
350 // whether IsExclusive is true or not.
351 using ResolveOrRejectValueParam =
352 std::conditional_t<IsExclusive, ResolveOrRejectValue&&,
353 const ResolveOrRejectValue&>;
354
355 using ResolveValueTypeParam =
356 std::conditional_t<IsExclusive, ResolveValueType&&,
357 const ResolveValueType&>;
358
359 using RejectValueTypeParam =
360 std::conditional_t<IsExclusive, RejectValueType&&,
361 const RejectValueType&>;
362
363 class AllSettledPromiseHolder : public MozPromiseRefcountable {
364 public:
365 explicit AllSettledPromiseHolder(size_t aDependentPromises)
366 : mPromise(new typename AllSettledPromiseType::Private(__func__)),
367 mOutstandingPromises(aDependentPromises) {
368 MOZ_ASSERT(aDependentPromises > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDependentPromises > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDependentPromises > 0)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDependentPromises > 0"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDependentPromises > 0"
")"); do { MOZ_CrashSequence(__null, 368); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
369 mValues.SetLength(aDependentPromises);
370 }
371
372 void Settle(size_t aIndex, ResolveOrRejectValueParam aValue) {
373 if (!mPromise) {
374 // Already rejected.
375 return;
376 }
377
378 mValues[aIndex].emplace(MaybeMove(aValue));
379 if (--mOutstandingPromises == 0) {
380 nsTArray<ResolveOrRejectValue> values;
381 values.SetCapacity(mValues.Length());
382 for (auto&& value : mValues) {
383 values.AppendElement(std::move(value.ref()));
384 }
385
386 mPromise->Resolve(std::move(values), __func__);
387 mPromise = nullptr;
388 mValues.Clear();
389 }
390 }
391
392 AllSettledPromiseType* Promise() { return mPromise; }
393
394 private:
395 nsTArray<Maybe<ResolveOrRejectValue>> mValues;
396 RefPtr<typename AllSettledPromiseType::Private> mPromise;
397 size_t mOutstandingPromises;
398 };
399
400 public:
401 [[nodiscard]] static RefPtr<AllPromiseType> All(
402 nsISerialEventTarget* aProcessingTarget,
403 nsTArray<RefPtr<MozPromise>>& aPromises) {
404 if (aPromises.Length() == 0) {
405 return AllPromiseType::CreateAndResolve(
406 CopyableTArray<ResolveValueType>(), __func__);
407 }
408
409 RefPtr holder = MakeRefPtr<AllPromiseHolder>(aPromises.Length());
410 RefPtr<AllPromiseType> promise = holder->Promise();
411 for (size_t i = 0; i < aPromises.Length(); ++i) {
412 aPromises[i]->Then(
413 aProcessingTarget, __func__,
414 [holder, i](ResolveValueTypeParam aResolveValue) -> void {
415 holder->Resolve(i, MaybeMove(aResolveValue));
416 },
417 [holder](RejectValueTypeParam aRejectValue) -> void {
418 holder->Reject(MaybeMove(aRejectValue));
419 });
420 }
421 return promise;
422 }
423
424 [[nodiscard]] static RefPtr<AllSettledPromiseType> AllSettled(
425 nsISerialEventTarget* aProcessingTarget,
426 nsTArray<RefPtr<MozPromise>>& aPromises) {
427 if (aPromises.Length() == 0) {
428 return AllSettledPromiseType::CreateAndResolve(
429 CopyableTArray<ResolveOrRejectValue>(), __func__);
430 }
431
432 RefPtr holder = MakeRefPtr<AllSettledPromiseHolder>(aPromises.Length());
433 RefPtr<AllSettledPromiseType> promise = holder->Promise();
434 for (size_t i = 0; i < aPromises.Length(); ++i) {
435 aPromises[i]->Then(aProcessingTarget, __func__,
436 [holder, i](ResolveOrRejectValueParam aValue) -> void {
437 holder->Settle(i, MaybeMove(aValue));
438 });
439 }
440 return promise;
441 }
442
443 class Request : public MozPromiseRefcountable {
444 public:
445 virtual void Disconnect() = 0;
446
447 protected:
448 Request() : mComplete(false), mDisconnected(false) {}
449 virtual ~Request() = default;
450
451 bool mComplete;
452 bool mDisconnected;
453 };
454
455 protected:
456 /*
457 * A ThenValue tracks a single consumer waiting on the promise. When a
458 * consumer invokes promise->Then(...), a ThenValue is created. Once the
459 * Promise is resolved or rejected, a {Resolve,Reject}Runnable is dispatched,
460 * which invokes the resolve/reject method and then deletes the ThenValue.
461 */
462 class ThenValueBase : public Request {
463 friend class MozPromise;
464 static const uint32_t sMagic = 0xfadece11;
465
466 public:
467 class ResolveOrRejectRunnable final
468 : public PrioritizableCancelableRunnable {
469 public:
470 ResolveOrRejectRunnable(ThenValueBase* aThenValue, MozPromise* aPromise)
471 : PrioritizableCancelableRunnable(
472 aPromise->mPriority,
473 "MozPromise::ThenValueBase::ResolveOrRejectRunnable"),
474 mThenValue(aThenValue),
475 mPromise(aPromise) {
476 MOZ_DIAGNOSTIC_ASSERT(!mPromise->IsPending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPromise->IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPromise->IsPending())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mPromise->IsPending()"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 476); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mPromise->IsPending()"
")"); do { MOZ_CrashSequence(__null, 476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
477 }
478
479#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
480 // nsINamed
481 NS_IMETHODvirtual nsresult GetName(nsACString& aName) override {
482 nsresult rv = PrioritizableCancelableRunnable::GetName(aName);
483 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
484 return rv;
485 }
486
487 if (mPromise) {
488 aName.Append(" ");
489 aName.Append(mPromise->mCreationSite);
490 };
491
492 return NS_OK;
493 }
494#endif
495
496 ~ResolveOrRejectRunnable() {
497 if (mThenValue) {
498 mThenValue->AssertIsDead();
499 }
500 }
501
502 NS_IMETHODvirtual nsresult Run() override {
503 PROMISE_LOG("ResolveOrRejectRunnable::Run() [this=%p]", this);
504 mThenValue->DoResolveOrReject(mPromise->Value());
505 mThenValue = nullptr;
506 mPromise = nullptr;
507 return NS_OK;
508 }
509
510 nsresult Cancel() override { return Run(); }
511
512 private:
513 RefPtr<ThenValueBase> mThenValue;
514 RefPtr<MozPromise> mPromise;
515 };
516
517 ThenValueBase(nsISerialEventTarget* aResponseTarget, StaticString aCallSite)
518 : mResponseTarget(aResponseTarget), mCallSite(aCallSite) {
519 MOZ_ASSERT(aResponseTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aResponseTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aResponseTarget))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aResponseTarget"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aResponseTarget"
")"); do { MOZ_CrashSequence(__null, 519); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
520 }
521
522#ifdef PROMISE_DEBUG
523 ~ThenValueBase() {
524 mMagic1 = 0;
525 mMagic2 = 0;
526 }
527#endif
528
529 void AssertIsDead() {
530 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic);
531 // We want to assert that this ThenValues is dead - that is to say, that
532 // there are no consumers waiting for the result. In the case of a normal
533 // ThenValue, we check that it has been disconnected, which is the way
534 // that the consumer signals that it no longer wishes to hear about the
535 // result. If this ThenValue has a completion promise (which is mutually
536 // exclusive with being disconnectable), we recursively assert that every
537 // ThenValue associated with the completion promise is dead.
538 if (MozPromiseBase* p = CompletionPromise()) {
539 p->AssertIsDead();
540 } else {
541#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
542 if (MOZ_UNLIKELY(!Request::mDisconnected)(__builtin_expect(!!(!Request::mDisconnected), 0))) {
543 MOZ_CRASH_UNSAFE_PRINTF(do { static_assert(2 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(2 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 548, MOZ_CrashPrintf("" "MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
, mCallSite.get(), mDispatchRv ? GetStaticErrorName(*mDispatchRv
) : "not dispatched")); } while (false)
544 "MozPromise::ThenValue created from '%s' destroyed without being "do { static_assert(2 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(2 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 548, MOZ_CrashPrintf("" "MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
, mCallSite.get(), mDispatchRv ? GetStaticErrorName(*mDispatchRv
) : "not dispatched")); } while (false)
545 "either disconnected, resolved, or rejected (dispatchRv: %s)",do { static_assert(2 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(2 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 548, MOZ_CrashPrintf("" "MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
, mCallSite.get(), mDispatchRv ? GetStaticErrorName(*mDispatchRv
) : "not dispatched")); } while (false)
546 mCallSite.get(),do { static_assert(2 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(2 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 548, MOZ_CrashPrintf("" "MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
, mCallSite.get(), mDispatchRv ? GetStaticErrorName(*mDispatchRv
) : "not dispatched")); } while (false)
547 mDispatchRv ? GetStaticErrorName(*mDispatchRv)do { static_assert(2 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(2 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 548, MOZ_CrashPrintf("" "MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
, mCallSite.get(), mDispatchRv ? GetStaticErrorName(*mDispatchRv
) : "not dispatched")); } while (false)
548 : "not dispatched")do { static_assert(2 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(2 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 548, MOZ_CrashPrintf("" "MozPromise::ThenValue created from '%s' destroyed without being "
"either disconnected, resolved, or rejected (dispatchRv: %s)"
, mCallSite.get(), mDispatchRv ? GetStaticErrorName(*mDispatchRv
) : "not dispatched")); } while (false)
;
549 }
550#endif
551 }
552 }
553
554 void Dispatch(MozPromise* aPromise) {
555 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic);
556 aPromise->mMutex.AssertCurrentThreadOwns();
557 MOZ_ASSERT(!aPromise->IsPending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPromise->IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPromise->IsPending())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aPromise->IsPending()"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 557); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromise->IsPending()"
")"); do { MOZ_CrashSequence(__null, 557); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
558
559 nsCOMPtr<nsIRunnable> r = new ResolveOrRejectRunnable(this, aPromise);
560 PROMISE_LOG(
561 "%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p] "
562 "%s dispatch",
563 aPromise->mValue.IsResolve() ? "Resolving" : "Rejecting",
564 mCallSite.get(), r.get(), aPromise, this,
565 aPromise->mUseSynchronousTaskDispatch ? "synchronous"
566 : aPromise->mUseDirectTaskDispatch ? "directtask"
567 : "normal");
568
569 if (aPromise->mUseSynchronousTaskDispatch &&
570 mResponseTarget->IsOnCurrentThread()) {
571 PROMISE_LOG("ThenValue::Dispatch running task synchronously [this=%p]",
572 this);
573 r->Run();
574 return;
575 }
576
577 if (aPromise->mUseDirectTaskDispatch &&
578 mResponseTarget->IsOnCurrentThread()) {
579 PROMISE_LOG(
580 "ThenValue::Dispatch dispatch task via direct task queue [this=%p]",
581 this);
582 nsCOMPtr<nsIDirectTaskDispatcher> dispatcher =
583 do_QueryInterface(mResponseTarget);
584 if (dispatcher) {
585 SetDispatchRv(dispatcher->DispatchDirectTask(r.forget()));
586 return;
587 }
588 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Direct Task dispatching not available for thread \"%s\""
, PR_GetThreadName(PR_GetCurrentThread())) .get(), nullptr, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 592)
589 nsPrintfCString(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Direct Task dispatching not available for thread \"%s\""
, PR_GetThreadName(PR_GetCurrentThread())) .get(), nullptr, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 592)
590 "Direct Task dispatching not available for thread \"%s\"",NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Direct Task dispatching not available for thread \"%s\""
, PR_GetThreadName(PR_GetCurrentThread())) .get(), nullptr, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 592)
591 PR_GetThreadName(PR_GetCurrentThread()))NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Direct Task dispatching not available for thread \"%s\""
, PR_GetThreadName(PR_GetCurrentThread())) .get(), nullptr, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 592)
592 .get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Direct Task dispatching not available for thread \"%s\""
, PR_GetThreadName(PR_GetCurrentThread())) .get(), nullptr, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 592)
;
593 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" " (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 596); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")"); do { MOZ_CrashSequence(__null, 596)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
594 false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 596); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")"); do { MOZ_CrashSequence(__null, 596)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
595 "mResponseTarget must implement nsIDirectTaskDispatcher for direct "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 596); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")"); do { MOZ_CrashSequence(__null, 596)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
596 "task dispatching")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 596); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")"); do { MOZ_CrashSequence(__null, 596)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
597 }
598
599 // Synchronous and direct task dispatch take precedence, as they apply to
600 // same-thread targets only and do not touch the target's event queue.
601 MOZ_ASSERT(!aPromise->mRequireTailDispatch ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPromise->mRequireTailDispatch || (mResponseTarget
->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH
) != nsIEventTarget::SUPPORTS_BASE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPromise->mRequireTailDispatch
|| (mResponseTarget->GetFeatures() & nsIEventTarget::
SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
" (" "This promise requires that Then() event targets support "
"tail dispatch" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
") (" "This promise requires that Then() event targets support "
"tail dispatch" ")"); do { MOZ_CrashSequence(__null, 606); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
602 (mResponseTarget->GetFeatures() &do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPromise->mRequireTailDispatch || (mResponseTarget
->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH
) != nsIEventTarget::SUPPORTS_BASE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPromise->mRequireTailDispatch
|| (mResponseTarget->GetFeatures() & nsIEventTarget::
SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
" (" "This promise requires that Then() event targets support "
"tail dispatch" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
") (" "This promise requires that Then() event targets support "
"tail dispatch" ")"); do { MOZ_CrashSequence(__null, 606); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
603 nsIEventTarget::SUPPORTS_TAIL_DISPATCH) !=do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPromise->mRequireTailDispatch || (mResponseTarget
->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH
) != nsIEventTarget::SUPPORTS_BASE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPromise->mRequireTailDispatch
|| (mResponseTarget->GetFeatures() & nsIEventTarget::
SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
" (" "This promise requires that Then() event targets support "
"tail dispatch" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
") (" "This promise requires that Then() event targets support "
"tail dispatch" ")"); do { MOZ_CrashSequence(__null, 606); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
604 nsIEventTarget::SUPPORTS_BASE,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPromise->mRequireTailDispatch || (mResponseTarget
->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH
) != nsIEventTarget::SUPPORTS_BASE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPromise->mRequireTailDispatch
|| (mResponseTarget->GetFeatures() & nsIEventTarget::
SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
" (" "This promise requires that Then() event targets support "
"tail dispatch" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
") (" "This promise requires that Then() event targets support "
"tail dispatch" ")"); do { MOZ_CrashSequence(__null, 606); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
605 "This promise requires that Then() event targets support "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPromise->mRequireTailDispatch || (mResponseTarget
->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH
) != nsIEventTarget::SUPPORTS_BASE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPromise->mRequireTailDispatch
|| (mResponseTarget->GetFeatures() & nsIEventTarget::
SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
" (" "This promise requires that Then() event targets support "
"tail dispatch" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
") (" "This promise requires that Then() event targets support "
"tail dispatch" ")"); do { MOZ_CrashSequence(__null, 606); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
606 "tail dispatch")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPromise->mRequireTailDispatch || (mResponseTarget
->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH
) != nsIEventTarget::SUPPORTS_BASE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPromise->mRequireTailDispatch
|| (mResponseTarget->GetFeatures() & nsIEventTarget::
SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
" (" "This promise requires that Then() event targets support "
"tail dispatch" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromise->mRequireTailDispatch || (mResponseTarget->GetFeatures() & nsIEventTarget::SUPPORTS_TAIL_DISPATCH) != nsIEventTarget::SUPPORTS_BASE"
") (" "This promise requires that Then() event targets support "
"tail dispatch" ")"); do { MOZ_CrashSequence(__null, 606); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
607
608 // Promise consumers are allowed to disconnect the Request object and
609 // then shut down the thread or task queue that the promise result would
610 // be dispatched on. So we unfortunately can't assert that promise
611 // dispatch succeeds. :-(
612 // We do record whether or not it succeeds so that if the ThenValueBase is
613 // then destroyed and it was not disconnected, we can include that
614 // information in the assertion message.
615 SetDispatchRv(mResponseTarget->Dispatch(r.forget()));
616 }
617
618 void Disconnect() override {
619 MOZ_DIAGNOSTIC_ASSERT(mResponseTarget->IsOnCurrentThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mResponseTarget->IsOnCurrentThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mResponseTarget->IsOnCurrentThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mResponseTarget->IsOnCurrentThread()"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 619); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mResponseTarget->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 619); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
620 MOZ_DIAGNOSTIC_ASSERT(!Request::mComplete)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!Request::mComplete)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!Request::mComplete))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!Request::mComplete"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 620); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!Request::mComplete"
")"); do { MOZ_CrashSequence(__null, 620); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
621 Request::mDisconnected = true;
622
623 // We could support rejecting the completion promise on disconnection, but
624 // then we'd need to have some sort of default reject value. The use cases
625 // of disconnection and completion promise chaining seem pretty
626 // orthogonal, so let's use assert against it.
627 MOZ_DIAGNOSTIC_ASSERT(!CompletionPromise())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!CompletionPromise())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!CompletionPromise()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!CompletionPromise()"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 627); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!CompletionPromise()"
")"); do { MOZ_CrashSequence(__null, 627); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
628 }
629
630 protected:
631 virtual MozPromiseBase* CompletionPromise() const = 0;
632 virtual void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) = 0;
633
634 void DoResolveOrReject(ResolveOrRejectValue& aValue) {
635 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic);
636 MOZ_DIAGNOSTIC_ASSERT(mResponseTarget->IsOnCurrentThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mResponseTarget->IsOnCurrentThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mResponseTarget->IsOnCurrentThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mResponseTarget->IsOnCurrentThread()"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 636); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mResponseTarget->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
637 Request::mComplete = true;
638 if (Request::mDisconnected) {
639 PROMISE_LOG(
640 "ThenValue::DoResolveOrReject disconnected - bailing out [this=%p]",
641 this);
642 return;
643 }
644
645 // Invoke the resolve or reject method.
646 DoResolveOrRejectInternal(aValue);
647 }
648
649 void SetDispatchRv(nsresult aRv) {
650#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
651 mDispatchRv = Some(aRv);
652#endif
653 }
654
655 nsCOMPtr<nsISerialEventTarget>
656 mResponseTarget; // May be released on any thread.
657#ifdef PROMISE_DEBUG
658 uint32_t mMagic1 = sMagic;
659#endif
660 StaticString mCallSite;
661#ifdef PROMISE_DEBUG
662 uint32_t mMagic2 = sMagic;
663#endif
664#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
665 Maybe<nsresult> mDispatchRv;
666#endif
667 };
668
669 /*
670 * Helper to make the resolve/reject value argument "optional".
671 */
672 template <typename ThisType, typename MethodType, typename ValueType>
673 static MethodReturnType<MethodType> InvokeMethod(ThisType* aThisVal,
674 MethodType aMethod,
675 ValueType&& aValue) {
676 if constexpr (TakesAnyArguments<MethodType>) {
677 return (aThisVal->*aMethod)(std::forward<ValueType>(aValue));
678 } else {
679 return (aThisVal->*aMethod)();
680 }
681 }
682
683 template <bool SupportChaining, typename PromiseType, typename ThisType,
684 typename MethodType, typename ValueType>
685 static RefPtr<PromiseType> InvokeCallbackMethod(ThisType* aThisVal,
686 MethodType aMethod,
687 ValueType&& aValue) {
688 if constexpr (SupportChaining) {
689 return InvokeMethod(aThisVal, aMethod, std::forward<ValueType>(aValue));
690 } else {
691 InvokeMethod(aThisVal, aMethod, std::forward<ValueType>(aValue));
692 return nullptr;
693 }
694 }
695
696 template <bool SupportChaining, typename PromiseType>
697 static void MaybeChain(PromiseType* aFrom,
698 RefPtr<typename PromiseType::Private>&& aTo) {
699 if constexpr (SupportChaining) {
700 if (aTo) {
701 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrom)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aFrom))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aFrom" " (" "Can't do promise chaining for a non-promise-returning method."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 703); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aFrom"
") (" "Can't do promise chaining for a non-promise-returning method."
")"); do { MOZ_CrashSequence(__null, 703); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
702 aFrom,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrom)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aFrom))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aFrom" " (" "Can't do promise chaining for a non-promise-returning method."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 703); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aFrom"
") (" "Can't do promise chaining for a non-promise-returning method."
")"); do { MOZ_CrashSequence(__null, 703); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
703 "Can't do promise chaining for a non-promise-returning method.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrom)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aFrom))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aFrom" " (" "Can't do promise chaining for a non-promise-returning method."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 703); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aFrom"
") (" "Can't do promise chaining for a non-promise-returning method."
")"); do { MOZ_CrashSequence(__null, 703); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
704 aFrom->ChainTo(aTo.forget(), "<chained completion promise>");
705 }
706 } else {
707 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTo)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!aTo))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aTo" " (" "A completion promise requires a promise-returning callback."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 708); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aTo"
") (" "A completion promise requires a promise-returning callback."
")"); do { MOZ_CrashSequence(__null, 708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
708 !aTo, "A completion promise requires a promise-returning callback.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTo)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(!aTo))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aTo" " (" "A completion promise requires a promise-returning callback."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 708); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aTo"
") (" "A completion promise requires a promise-returning callback."
")"); do { MOZ_CrashSequence(__null, 708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
709 }
710 }
711
712 template <typename>
713 class ThenCommand;
714
715 template <typename...>
716 class ThenValue;
717
718 template <typename ThisType, typename ResolveMethodType,
719 typename RejectMethodType>
720 class ThenValue<ThisType*, ResolveMethodType, RejectMethodType>
721 : public ThenValueBase {
722 friend class ThenCommand<ThenValue>;
723
724 using R1 = RemoveSmartPointer<MethodReturnType<ResolveMethodType>>;
725 using R2 = RemoveSmartPointer<MethodReturnType<RejectMethodType>>;
726 constexpr static bool SupportChaining =
727 IsMozPromise<R1> && std::is_same_v<R1, R2>;
728
729 // Fall back to MozPromise when promise chaining is not supported to make
730 // code compile.
731 using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
732
733 public:
734 ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
735 ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
736 StaticString aCallSite)
737 : ThenValueBase(aResponseTarget, aCallSite),
738 mThisVal(aThisVal),
739 mResolveMethod(aResolveMethod),
740 mRejectMethod(aRejectMethod) {}
741
742 void Disconnect() override {
743 ThenValueBase::Disconnect();
744
745 // If a Request has been disconnected, we don't guarantee that the
746 // resolve/reject runnable will be dispatched. Null out our refcounted
747 // this-value now so that it's released predictably on the dispatch
748 // thread.
749 mThisVal = nullptr;
750 }
751
752 protected:
753 MozPromiseBase* CompletionPromise() const override {
754 return mCompletionPromise;
755 }
756
757 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
758 RefPtr<PromiseType> result =
759 aValue.IsResolve()
760 ? InvokeCallbackMethod<SupportChaining, PromiseType>(
761 mThisVal.get(), mResolveMethod,
762 MaybeMove(aValue.ResolveValue()))
763 : InvokeCallbackMethod<SupportChaining, PromiseType>(
764 mThisVal.get(), mRejectMethod,
765 MaybeMove(aValue.RejectValue()));
766
767 // Null out mThisVal after invoking the callback so that any references
768 // are released predictably on the dispatch thread. Otherwise, it would be
769 // released on whatever thread last drops its reference to the ThenValue,
770 // which may or may not be ok.
771 mThisVal = nullptr;
772
773 MaybeChain<SupportChaining, PromiseType>(result,
774 std::move(mCompletionPromise));
775 }
776
777 private:
778 RefPtr<ThisType>
779 mThisVal; // Only accessed and refcounted on dispatch thread.
780 ResolveMethodType mResolveMethod;
781 RejectMethodType mRejectMethod;
782 RefPtr<typename PromiseType::Private> mCompletionPromise;
783 };
784
785 template <typename ThisType, typename ResolveRejectMethodType>
786 class ThenValue<ThisType*, ResolveRejectMethodType> : public ThenValueBase {
787 friend class ThenCommand<ThenValue>;
788
789 using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectMethodType>>;
790 constexpr static bool SupportChaining = IsMozPromise<R1>;
791
792 // Fall back to MozPromise when promise chaining is not supported to make
793 // code compile.
794 using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
795
796 public:
797 ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
798 ResolveRejectMethodType aResolveRejectMethod,
799 StaticString aCallSite)
800 : ThenValueBase(aResponseTarget, aCallSite),
801 mThisVal(aThisVal),
802 mResolveRejectMethod(aResolveRejectMethod) {}
803
804 void Disconnect() override {
805 ThenValueBase::Disconnect();
806
807 // If a Request has been disconnected, we don't guarantee that the
808 // resolve/reject runnable will be dispatched. Null out our refcounted
809 // this-value now so that it's released predictably on the dispatch
810 // thread.
811 mThisVal = nullptr;
812 }
813
814 protected:
815 MozPromiseBase* CompletionPromise() const override {
816 return mCompletionPromise;
817 }
818
819 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
820 RefPtr<PromiseType> result =
821 InvokeCallbackMethod<SupportChaining, PromiseType>(
822 mThisVal.get(), mResolveRejectMethod, MaybeMove(aValue));
823
824 // Null out mThisVal after invoking the callback so that any references
825 // are released predictably on the dispatch thread. Otherwise, it would be
826 // released on whatever thread last drops its reference to the ThenValue,
827 // which may or may not be ok.
828 mThisVal = nullptr;
829
830 MaybeChain<SupportChaining, PromiseType>(result,
831 std::move(mCompletionPromise));
832 }
833
834 private:
835 RefPtr<ThisType>
836 mThisVal; // Only accessed and refcounted on dispatch thread.
837 ResolveRejectMethodType mResolveRejectMethod;
838 RefPtr<typename PromiseType::Private> mCompletionPromise;
839 };
840
841 // NB: We could use std::function here instead of a template if it were
842 // supported. :-(
843 template <typename ResolveFunction, typename RejectFunction>
844 class ThenValue<ResolveFunction, RejectFunction> : public ThenValueBase {
845 friend class ThenCommand<ThenValue>;
846
847 using R1 = RemoveSmartPointer<MethodReturnType<ResolveFunction>>;
848 using R2 = RemoveSmartPointer<MethodReturnType<RejectFunction>>;
849 constexpr static bool SupportChaining =
850 IsMozPromise<R1> && std::is_same_v<R1, R2>;
851
852 // Fall back to MozPromise when promise chaining is not supported to make
853 // code compile.
854 using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
855
856 public:
857 ThenValue(nsISerialEventTarget* aResponseTarget,
858 ResolveFunction&& aResolveFunction,
859 RejectFunction&& aRejectFunction, StaticString aCallSite)
860 : ThenValueBase(aResponseTarget, aCallSite) {
861 mResolveFunction.emplace(std::move(aResolveFunction));
862 mRejectFunction.emplace(std::move(aRejectFunction));
863 }
864
865 void Disconnect() override {
866 ThenValueBase::Disconnect();
867
868 // If a Request has been disconnected, we don't guarantee that the
869 // resolve/reject runnable will be dispatched. Destroy our callbacks
870 // now so that any references in closures are released predictable on
871 // the dispatch thread.
872 mResolveFunction.reset();
873 mRejectFunction.reset();
874 }
875
876 protected:
877 MozPromiseBase* CompletionPromise() const override {
878 return mCompletionPromise;
879 }
880
881 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
882 // Note: The usage of InvokeCallbackMethod here requires that
883 // ResolveFunction/RejectFunction are capture-lambdas (i.e. anonymous
884 // classes with ::operator()), since it allows us to share code more
885 // easily. We could fix this if need be, though it's quite easy to work
886 // around by just capturing something.
887 RefPtr<PromiseType> result =
888 aValue.IsResolve()
889 ? InvokeCallbackMethod<SupportChaining, PromiseType>(
890 mResolveFunction.ptr(), &ResolveFunction::operator(),
891 MaybeMove(aValue.ResolveValue()))
892 : InvokeCallbackMethod<SupportChaining, PromiseType>(
893 mRejectFunction.ptr(), &RejectFunction::operator(),
894 MaybeMove(aValue.RejectValue()));
895
896 // Destroy callbacks after invocation so that any references in closures
897 // are released predictably on the dispatch thread. Otherwise, they would
898 // be released on whatever thread last drops its reference to the
899 // ThenValue, which may or may not be ok.
900 mResolveFunction.reset();
901 mRejectFunction.reset();
902
903 MaybeChain<SupportChaining, PromiseType>(result,
904 std::move(mCompletionPromise));
905 }
906
907 private:
908 Maybe<ResolveFunction>
909 mResolveFunction; // Only accessed and deleted on dispatch thread.
910 Maybe<RejectFunction>
911 mRejectFunction; // Only accessed and deleted on dispatch thread.
912 RefPtr<typename PromiseType::Private> mCompletionPromise;
913 };
914
915 template <typename ResolveRejectFunction>
916 class ThenValue<ResolveRejectFunction> : public ThenValueBase {
917 friend class ThenCommand<ThenValue>;
918
919 using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectFunction>>;
920 constexpr static bool SupportChaining = IsMozPromise<R1>;
921
922 // Fall back to MozPromise when promise chaining is not supported to make
923 // code compile.
924 using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
925
926 public:
927 ThenValue(nsISerialEventTarget* aResponseTarget,
928 ResolveRejectFunction&& aResolveRejectFunction,
929 StaticString aCallSite)
930 : ThenValueBase(aResponseTarget, aCallSite) {
931 mResolveRejectFunction.emplace(std::move(aResolveRejectFunction));
932 }
933
934 void Disconnect() override {
935 ThenValueBase::Disconnect();
936
937 // If a Request has been disconnected, we don't guarantee that the
938 // resolve/reject runnable will be dispatched. Destroy our callbacks
939 // now so that any references in closures are released predictable on
940 // the dispatch thread.
941 mResolveRejectFunction.reset();
942 }
943
944 protected:
945 MozPromiseBase* CompletionPromise() const override {
946 return mCompletionPromise;
947 }
948
949 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
950 // Note: The usage of InvokeCallbackMethod here requires that
951 // ResolveRejectFunction is capture-lambdas (i.e. anonymous
952 // classes with ::operator()), since it allows us to share code more
953 // easily. We could fix this if need be, though it's quite easy to work
954 // around by just capturing something.
955 RefPtr<PromiseType> result =
956 InvokeCallbackMethod<SupportChaining, PromiseType>(
957 mResolveRejectFunction.ptr(), &ResolveRejectFunction::operator(),
958 MaybeMove(aValue));
959
960 // Destroy callbacks after invocation so that any references in closures
961 // are released predictably on the dispatch thread. Otherwise, they would
962 // be released on whatever thread last drops its reference to the
963 // ThenValue, which may or may not be ok.
964 mResolveRejectFunction.reset();
965
966 MaybeChain<SupportChaining, PromiseType>(result,
967 std::move(mCompletionPromise));
968 }
969
970 private:
971 Maybe<ResolveRejectFunction>
972 mResolveRejectFunction; // Only accessed and deleted on dispatch
973 // thread.
974 RefPtr<typename PromiseType::Private> mCompletionPromise;
975 };
976
977 template <typename ResolveFunction>
978 class MapValue final : public ThenValueBase {
979 friend class ThenCommand<MapValue>;
980 constexpr static const bool SupportChaining = true;
981 using ResolveValueT_ = std::invoke_result_t<ResolveFunction, ResolveValueT>;
982 using PromiseType = MozPromise<ResolveValueT_, RejectValueT, IsExclusive>;
983
984 public:
985 explicit MapValue(nsISerialEventTarget* aResponseTarget,
986 ResolveFunction&& f, StaticString aCallSite)
987 : ThenValueBase(aResponseTarget, aCallSite),
988 mResolveFunction(Some(std::forward<ResolveFunction>(f))) {}
989
990 protected:
991 void Disconnect() override {
992 ThenValueBase::Disconnect();
993 mResolveFunction.reset();
994 }
995
996 MozPromiseBase* CompletionPromise() const override {
997 return mCompletionPromise;
998 }
999
1000 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
1001 // Note that promise-chaining is always supported here; this function can
1002 // only transform from MozPromise<A, B, k> to MozPromise<A2, B, k>.
1003 auto value = MaybeMove(aValue);
1004 typename PromiseType::ResolveOrRejectValue output;
1005
1006 if (value.IsResolve()) {
1007 output.SetResolve((*mResolveFunction)(std::move(value.ResolveValue())));
1008 } else {
1009 output.SetReject(std::move(value.RejectValue()));
1010 }
1011
1012 if (mCompletionPromise) {
1013 mCompletionPromise->ResolveOrReject(std::move(output),
1014 ThenValueBase::mCallSite);
1015 }
1016 }
1017
1018 private:
1019 Maybe<ResolveFunction> mResolveFunction;
1020 RefPtr<typename PromiseType::Private> mCompletionPromise;
1021 };
1022
1023 template <typename RejectFunction>
1024 class MapErrValue final : public ThenValueBase {
1025 friend class ThenCommand<MapErrValue>;
1026 constexpr static const bool SupportChaining = true;
1027 using RejectValueT_ = std::invoke_result_t<RejectFunction, RejectValueT>;
1028 using PromiseType = MozPromise<ResolveValueT, RejectValueT_, IsExclusive>;
1029
1030 public:
1031 explicit MapErrValue(nsISerialEventTarget* aResponseTarget,
1032 RejectFunction&& f, StaticString aCallSite)
1033 : ThenValueBase(aResponseTarget, aCallSite),
1034 mRejectFunction(Some(std::forward<RejectFunction>(f))) {}
1035
1036 protected:
1037 void Disconnect() override {
1038 ThenValueBase::Disconnect();
1039 mRejectFunction.reset();
1040 }
1041
1042 MozPromiseBase* CompletionPromise() const override {
1043 return mCompletionPromise;
1044 }
1045
1046 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
1047 // Note that promise-chaining is always supported here; this function can
1048 // only transform from MozPromise<A, B, k> to MozPromise<A, B2, k>.
1049 auto value = MaybeMove(aValue);
1050 typename PromiseType::ResolveOrRejectValue output;
1051
1052 if (value.IsResolve()) {
1053 output.SetResolve(std::move(value.ResolveValue()));
1054 } else {
1055 output.SetReject((*mRejectFunction)(std::move(value.RejectValue())));
1056 }
1057
1058 if (mCompletionPromise) {
1059 mCompletionPromise->ResolveOrReject(std::move(output),
1060 ThenValueBase::mCallSite);
1061 }
1062 }
1063
1064 private:
1065 Maybe<RejectFunction> mRejectFunction;
1066 RefPtr<typename PromiseType::Private> mCompletionPromise;
1067 };
1068
1069 public:
1070 void ThenInternal(already_AddRefed<ThenValueBase> aThenValue,
1071 StaticString aCallSite) {
1072 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1073 mMagic3 == sMagic && mMagic4 == &mMutex);
1074 RefPtr<ThenValueBase> thenValue = aThenValue;
1075 MutexAutoLock lock(mMutex);
1076 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsExclusive || !mHaveRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsExclusive || !mHaveRequest
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!IsExclusive || !mHaveRequest" " (" "Using an exclusive promise in a non-exclusive fashion"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1078); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1078); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1077 !IsExclusive || !mHaveRequest,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsExclusive || !mHaveRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsExclusive || !mHaveRequest
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!IsExclusive || !mHaveRequest" " (" "Using an exclusive promise in a non-exclusive fashion"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1078); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1078); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1078 "Using an exclusive promise in a non-exclusive fashion")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsExclusive || !mHaveRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsExclusive || !mHaveRequest
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!IsExclusive || !mHaveRequest" " (" "Using an exclusive promise in a non-exclusive fashion"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1078); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1078); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1079 mHaveRequest = true;
1080 PROMISE_LOG("%s invoking Then() [this=%p, aThenValue=%p, isPending=%d]",
1081 aCallSite.get(), this, thenValue.get(), (int)IsPending());
1082 if (!IsPending()) {
1083 thenValue->Dispatch(this);
1084 } else {
1085 mThenValues.AppendElement(thenValue.forget());
1086 }
1087 }
1088
1089 protected:
1090 /*
1091 * A command object to store all information needed to make a request to the
1092 * promise. This allows us to delay the request until further use is known
1093 * (whether it is ->Then() again for more promise chaining or ->Track() to
1094 * terminate chaining and issue the request).
1095 *
1096 * This allows a unified syntax for promise chaining and disconnection, and
1097 * feels more like its JS counterpart.
1098 *
1099 * Note that a ThenCommand is always exclusive, even if its source or result
1100 * promises are not. To attach multiple continuations, explicitly convert it
1101 * to a promise first.
1102 */
1103 template <typename ThenValueType>
1104 class MOZ_TEMPORARY_CLASS ThenCommand {
1105 // Allow Promise1::ThenCommand to access the private constructor
1106 // Promise2::ThenCommand(ThenCommand&&).
1107 template <typename, typename, bool>
1108 friend class MozPromise;
1109
1110 using PromiseType = typename ThenValueType::PromiseType;
1111 using Private = typename PromiseType::Private;
1112
1113 ThenCommand(StaticString aCallSite,
1114 already_AddRefed<ThenValueType> aThenValue,
1115 MozPromise* aReceiver)
1116 : mCallSite(aCallSite), mThenValue(aThenValue), mReceiver(aReceiver) {}
1117
1118 ThenCommand(ThenCommand&& aOther) noexcept = default;
1119
1120 public:
1121 ~ThenCommand() {
1122 // Issue the request now if the return value of Then() is not used.
1123 if (mThenValue) {
34
Taking false branch
1124 mReceiver->ThenInternal(mThenValue.forget(), mCallSite);
1125 }
1126 }
35
Calling '~RefPtr'
1127
1128 // Allow RefPtr<MozPromise> p = somePromise->Then();
1129 // p->Then(thread1, ...);
1130 // p->Then(thread2, ...);
1131 operator RefPtr<PromiseType>() {
1132 static_assert(
1133 ThenValueType::SupportChaining,
1134 "The resolve/reject callback needs to return a RefPtr<MozPromise> "
1135 "in order to do promise chaining.");
1136
1137 // mCompletionPromise must be created before ThenInternal() to avoid race.
1138 RefPtr<Private> p =
1139 new Private("<completion promise>", true /* aIsCompletionPromise */);
1140 mThenValue->mCompletionPromise = p;
1141 // Note ThenInternal() might nullify mCompletionPromise before return.
1142 // So we need to return p instead of mCompletionPromise.
1143 mReceiver->ThenInternal(mThenValue.forget(), mCallSite);
1144 return p;
1145 }
1146
1147 template <typename... Ts>
1148 auto Then(Ts&&... aArgs) -> decltype(std::declval<PromiseType>().Then(
1149 std::forward<Ts>(aArgs)...)) {
1150 return static_cast<RefPtr<PromiseType>>(*this)->Then(
1151 std::forward<Ts>(aArgs)...);
1152 }
1153
1154 template <typename... Ts>
1155 auto Map(Ts&&... aArgs) -> decltype(std::declval<PromiseType>().Map(
1156 std::forward<Ts>(aArgs)...)) {
1157 return static_cast<RefPtr<PromiseType>>(*this)->Map(
1158 std::forward<Ts>(aArgs)...);
1159 }
1160
1161 template <typename... Ts>
1162 auto MapErr(Ts&&... aArgs) -> decltype(std::declval<PromiseType>().MapErr(
1163 std::forward<Ts>(aArgs)...)) {
1164 return static_cast<RefPtr<PromiseType>>(*this)->MapErr(
1165 std::forward<Ts>(aArgs)...);
1166 }
1167
1168 void Track(MozPromiseRequestHolder<MozPromise>& aRequestHolder) {
1169 aRequestHolder.Track(do_AddRef(mThenValue));
1170 mReceiver->ThenInternal(mThenValue.forget(), mCallSite);
1171 }
1172
1173 // Allow calling ->Then() again for more promise chaining or ->Track() to
1174 // end chaining and track the request for future disconnection.
1175 ThenCommand* operator->() { return this; }
1176
1177 private:
1178 StaticString mCallSite;
1179 RefPtr<ThenValueType> mThenValue;
1180 RefPtr<MozPromise> mReceiver;
1181 };
1182
1183 public:
1184 template <typename ThisType, typename... Methods,
1185 typename ThenValueType = ThenValue<ThisType*, Methods...>,
1186 typename ReturnType = ThenCommand<ThenValueType>>
1187 ReturnType Then(nsISerialEventTarget* aResponseTarget, StaticString aCallSite,
1188 ThisType* aThisVal, Methods... aMethods) {
1189 RefPtr<ThenValueType> thenValue =
1190 new ThenValueType(aResponseTarget, aThisVal, aMethods..., aCallSite);
1191 return ReturnType(aCallSite, thenValue.forget(), this);
1192 }
1193
1194 template <typename... Functions,
1195 typename ThenValueType = ThenValue<Functions...>,
1196 typename ReturnType = ThenCommand<ThenValueType>>
1197 ReturnType Then(nsISerialEventTarget* aResponseTarget, StaticString aCallSite,
1198 Functions&&... aFunctions) {
1199 RefPtr<ThenValueType> thenValue =
1200 new ThenValueType(aResponseTarget, std::move(aFunctions)..., aCallSite);
1201 return ReturnType(aCallSite, thenValue.forget(), this);
1202 }
1203
1204 // Shorthand for a `Then` which simply forwards the reject-value, but performs
1205 // some additional work with the resolve-value.
1206 template <typename Function>
1207 auto Map(nsISerialEventTarget* aResponseTarget, StaticString aCallSite,
1208 Function&& function) {
1209 RefPtr<MapValue<Function>> thenValue = new MapValue<Function>(
1210 aResponseTarget, std::forward<Function>(function), aCallSite);
1211 return ThenCommand<MapValue<Function>>(aCallSite, thenValue.forget(), this);
1212 }
1213
1214 // Shorthand for a `Then` which simply forwards the resolve-value, but
1215 // performs some additional work with the reject-value.
1216 template <typename Function>
1217 auto MapErr(nsISerialEventTarget* aResponseTarget, StaticString aCallSite,
1218 Function&& function) {
1219 RefPtr<MapErrValue<Function>> thenValue = new MapErrValue<Function>(
1220 aResponseTarget, std::forward<Function>(function), aCallSite);
1221 return ThenCommand<MapErrValue<Function>>(aCallSite, thenValue.forget(),
1222 this);
1223 }
1224
1225 void ChainTo(already_AddRefed<Private> aChainedPromise,
1226 StaticString aCallSite) {
1227 MutexAutoLock lock(mMutex);
1228 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsExclusive || !mHaveRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsExclusive || !mHaveRequest
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!IsExclusive || !mHaveRequest" " (" "Using an exclusive promise in a non-exclusive fashion"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1230); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1230); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1229 !IsExclusive || !mHaveRequest,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsExclusive || !mHaveRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsExclusive || !mHaveRequest
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!IsExclusive || !mHaveRequest" " (" "Using an exclusive promise in a non-exclusive fashion"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1230); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1230); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1230 "Using an exclusive promise in a non-exclusive fashion")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsExclusive || !mHaveRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsExclusive || !mHaveRequest
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!IsExclusive || !mHaveRequest" " (" "Using an exclusive promise in a non-exclusive fashion"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1230); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1230); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1231 mHaveRequest = true;
1232 RefPtr<Private> chainedPromise = aChainedPromise;
1233 PROMISE_LOG(
1234 "%s invoking Chain() [this=%p, chainedPromise=%p, isPending=%d]",
1235 aCallSite.get(), this, chainedPromise.get(), (int)IsPending());
1236
1237 // We want to use the same type of dispatching method with the chained
1238 // promises.
1239
1240 // We need to ensure that the UseSynchronousTaskDispatch branch isn't taken
1241 // at compilation time to ensure we're not triggering the static_assert in
1242 // UseSynchronousTaskDispatch method. if constexpr (IsExclusive) ensures
1243 // that.
1244 if (mUseDirectTaskDispatch) {
1245 chainedPromise->UseDirectTaskDispatch(aCallSite);
1246 } else if constexpr (IsExclusive) {
1247 if (mUseSynchronousTaskDispatch) {
1248 chainedPromise->UseSynchronousTaskDispatch(aCallSite);
1249 }
1250 } else {
1251 chainedPromise->SetTaskPriority(mPriority, aCallSite);
1252 }
1253
1254 if (!IsPending()) {
1255 ForwardTo(chainedPromise);
1256 } else {
1257 mChainedPromises.AppendElement(chainedPromise);
1258 }
1259 }
1260
1261#ifdef MOZ_WIDGET_ANDROID
1262 // Creates a C++ MozPromise from its Java counterpart, GeckoResult.
1263 [[nodiscard]] static RefPtr<MozPromise> FromGeckoResult(
1264 java::GeckoResult::Param aGeckoResult) {
1265 using jni::GeckoResultCallback;
1266 RefPtr<Private> p = new Private("GeckoResult Glue", false);
1267 auto resolve = GeckoResultCallback::CreateAndAttach<ResolveValueType>(
1268 [p](ResolveValueType&& aArg) {
1269 p->Resolve(MaybeMove(aArg), __func__);
1270 });
1271 auto reject = GeckoResultCallback::CreateAndAttach<RejectValueType>(
1272 [p](RejectValueType&& aArg) { p->Reject(MaybeMove(aArg), __func__); });
1273 aGeckoResult->NativeThen(resolve, reject);
1274 return p;
1275 }
1276#endif
1277
1278 // Note we expose the function AssertIsDead() instead of IsDead() since
1279 // checking IsDead() is a data race in the situation where the request is not
1280 // dead. Therefore we enforce the form |Assert(IsDead())| by exposing
1281 // AssertIsDead() only.
1282 void AssertIsDead() override {
1283 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1284 mMagic3 == sMagic && mMagic4 == &mMutex);
1285 MutexAutoLock lock(mMutex);
1286 for (auto&& then : mThenValues) {
1287 then->AssertIsDead();
1288 }
1289 for (auto&& chained : mChainedPromises) {
1290 chained->AssertIsDead();
1291 }
1292 }
1293
1294 protected:
1295 // NOTE: Methods like `IsPending()` and `Value()` are intentionally marked as
1296 // `protected`, as they are not safe to call from outside of the MozPromise
1297 // code. The only way to inspect the state of a MozPromise is intentionally
1298 // to call `->Then` on the promise, and receive an async callback.
1299 //
1300 // MozPromise has somewhat complex locking and thread safety properties which
1301 // can't be extended outside of the code in this file.
1302 bool IsPending() const { return mValue.IsNothing(); }
1303
1304 ResolveOrRejectValue& Value() {
1305 // This method should only be called once the value has stabilized. As
1306 // such, we don't need to acquire the lock here.
1307 MOZ_DIAGNOSTIC_ASSERT(!IsPending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsPending()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!IsPending()", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1307); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsPending()"
")"); do { MOZ_CrashSequence(__null, 1307); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1308 return mValue;
1309 }
1310
1311 void DispatchAll() {
1312 mMutex.AssertCurrentThreadOwns();
1313 for (auto&& thenValue : mThenValues) {
1314 thenValue->Dispatch(this);
1315 }
1316 mThenValues.Clear();
1317
1318 for (auto&& chainedPromise : mChainedPromises) {
1319 ForwardTo(chainedPromise);
1320 }
1321 mChainedPromises.Clear();
1322 }
1323
1324 void ForwardTo(Private* aOther) {
1325 MOZ_ASSERT(!IsPending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsPending()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!IsPending()", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsPending()"
")"); do { MOZ_CrashSequence(__null, 1325); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1326 if (mValue.IsResolve()) {
1327 aOther->Resolve(MaybeMove(mValue.ResolveValue()), "<chained promise>");
1328 } else {
1329 aOther->Reject(MaybeMove(mValue.RejectValue()), "<chained promise>");
1330 }
1331 }
1332
1333 virtual ~MozPromise() {
1334 PROMISE_LOG("MozPromise::~MozPromise [this=%p]", this);
1335 AssertIsDead();
1336 // We can't guarantee a completion promise will always be revolved or
1337 // rejected since ResolveOrRejectRunnable might not run when dispatch fails.
1338 if (!mIsCompletionPromise) {
1339 MOZ_ASSERT(!IsPending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsPending()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!IsPending()", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsPending()"
")"); do { MOZ_CrashSequence(__null, 1339); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1340 MOZ_ASSERT(mThenValues.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mThenValues.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mThenValues.IsEmpty()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("mThenValues.IsEmpty()"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mThenValues.IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1340); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1341 MOZ_ASSERT(mChainedPromises.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mChainedPromises.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mChainedPromises.IsEmpty()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mChainedPromises.IsEmpty()"
, "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1341); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChainedPromises.IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1341); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1342 }
1343#ifdef PROMISE_DEBUG
1344 mMagic1 = 0;
1345 mMagic2 = 0;
1346 mMagic3 = 0;
1347 mMagic4 = nullptr;
1348#endif
1349 };
1350
1351 StaticString mCreationSite; // For logging and profiling
1352 Mutex mMutex MOZ_UNANNOTATED;
1353 ResolveOrRejectValue mValue;
1354 bool mUseSynchronousTaskDispatch = false;
1355 bool mUseDirectTaskDispatch = false;
1356#ifdef DEBUG1
1357 bool mRequireTailDispatch = false;
1358#endif
1359 uint32_t mPriority = nsIRunnablePriority::PRIORITY_NORMAL;
1360#ifdef PROMISE_DEBUG
1361 uint32_t mMagic1 = sMagic;
1362#endif
1363 // Try shows we never have more than 3 elements when IsExclusive is false.
1364 // So '3' is a good value to avoid heap allocation in most cases.
1365 AutoTArray<RefPtr<ThenValueBase>, IsExclusive ? 1 : 3> mThenValues;
1366#ifdef PROMISE_DEBUG
1367 uint32_t mMagic2 = sMagic;
1368#endif
1369 nsTArray<RefPtr<Private>> mChainedPromises;
1370#ifdef PROMISE_DEBUG
1371 uint32_t mMagic3 = sMagic;
1372#endif
1373 bool mHaveRequest;
1374 const bool mIsCompletionPromise;
1375#ifdef PROMISE_DEBUG
1376 void* mMagic4;
1377#endif
1378};
1379
1380template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
1381class MozPromise<ResolveValueT, RejectValueT, IsExclusive>::Private
1382 : public MozPromise<ResolveValueT, RejectValueT, IsExclusive> {
1383 public:
1384 explicit Private(StaticString aCreationSite,
1385 bool aIsCompletionPromise = false)
1386 : MozPromise(aCreationSite, aIsCompletionPromise) {}
1387
1388 template <typename ResolveValueT_>
1389 void Resolve(ResolveValueT_&& aResolveValue, StaticString aResolveSite) {
1390 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1391 mMagic3 == sMagic && mMagic4 == &mMutex);
1392 MutexAutoLock lock(mMutex);
1393 PROMISE_LOG("%s resolving MozPromise (%p created at %s)",
1394 aResolveSite.get(), this, mCreationSite.get());
1395 if (!IsPending()) {
1396 PROMISE_LOG(
1397 "%s ignored already resolved or rejected MozPromise (%p created at "
1398 "%s)",
1399 aResolveSite.get(), this, mCreationSite.get());
1400 return;
1401 }
1402 mValue.SetResolve(std::forward<ResolveValueT_>(aResolveValue));
1403 DispatchAll();
1404 }
1405
1406 template <typename RejectValueT_>
1407 void Reject(RejectValueT_&& aRejectValue, StaticString aRejectSite) {
1408 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1409 mMagic3 == sMagic && mMagic4 == &mMutex);
1410 MutexAutoLock lock(mMutex);
1411 PROMISE_LOG("%s rejecting MozPromise (%p created at %s)", aRejectSite.get(),
1412 this, mCreationSite.get());
1413 if (!IsPending()) {
1414 PROMISE_LOG(
1415 "%s ignored already resolved or rejected MozPromise (%p created at "
1416 "%s)",
1417 aRejectSite.get(), this, mCreationSite.get());
1418 return;
1419 }
1420 mValue.SetReject(std::forward<RejectValueT_>(aRejectValue));
1421 DispatchAll();
1422 }
1423
1424 template <typename ResolveOrRejectValue_>
1425 void ResolveOrReject(ResolveOrRejectValue_&& aValue, StaticString aSite) {
1426 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1427 mMagic3 == sMagic && mMagic4 == &mMutex);
1428 MutexAutoLock lock(mMutex);
1429 PROMISE_LOG("%s resolveOrRejecting MozPromise (%p created at %s)",
1430 aSite.get(), this, mCreationSite.get());
1431 if (!IsPending()) {
1432 PROMISE_LOG(
1433 "%s ignored already resolved or rejected MozPromise (%p created at "
1434 "%s)",
1435 aSite.get(), this, mCreationSite.get());
1436 return;
1437 }
1438 mValue = std::forward<ResolveOrRejectValue_>(aValue);
1439 DispatchAll();
1440 }
1441
1442 // If the caller and target are both on the same thread, run the the resolve
1443 // or reject callback synchronously. Otherwise, the task will be dispatched
1444 // via the target Dispatch method.
1445 void UseSynchronousTaskDispatch(const char* aSite) {
1446 static_assert(
1447 IsExclusive,
1448 "Synchronous dispatch can only be used with exclusive promises");
1449 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1450 mMagic3 == sMagic && mMagic4 == &mMutex);
1451 MutexAutoLock lock(mMutex);
1452 PROMISE_LOG("%s UseSynchronousTaskDispatch MozPromise (%p created at %s)",
1453 aSite, this, mCreationSite.get());
1454 MOZ_ASSERT(IsPending(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1456
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1455 "A Promise must not have been already resolved or rejected to "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1456
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1456 "set dispatch state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1456
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1457 mUseSynchronousTaskDispatch = true;
1458 }
1459
1460 // If the caller and target are both on the same thread, run the
1461 // resolve/reject callback off the direct task queue instead. This avoids a
1462 // full trip to the back of the event queue for each additional asynchronous
1463 // step when using MozPromise, and is similar (but not identical to) the
1464 // microtask semantics of JS promises.
1465 void UseDirectTaskDispatch(const char* aSite) {
1466 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1467 mMagic3 == sMagic && mMagic4 == &mMutex);
1468 MutexAutoLock lock(mMutex);
1469 PROMISE_LOG("%s UseDirectTaskDispatch MozPromise (%p created at %s)", aSite,
1470 this, mCreationSite.get());
1471 MOZ_ASSERT(IsPending(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1473
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1472 "A Promise must not have been already resolved or rejected to "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1473
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1473 "set dispatch state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1473
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1474 MOZ_ASSERT(!mUseSynchronousTaskDispatch,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mUseSynchronousTaskDispatch)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mUseSynchronousTaskDispatch
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mUseSynchronousTaskDispatch" " (" "Promise already set for synchronous dispatch"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseSynchronousTaskDispatch"
") (" "Promise already set for synchronous dispatch" ")"); do
{ MOZ_CrashSequence(__null, 1475); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1475 "Promise already set for synchronous dispatch")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mUseSynchronousTaskDispatch)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mUseSynchronousTaskDispatch
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mUseSynchronousTaskDispatch" " (" "Promise already set for synchronous dispatch"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseSynchronousTaskDispatch"
") (" "Promise already set for synchronous dispatch" ")"); do
{ MOZ_CrashSequence(__null, 1475); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1476 mUseDirectTaskDispatch = true;
1477 }
1478
1479 // If the resolve/reject will be handled on a thread supporting priorities,
1480 // one may want to tweak the priority of the task by passing a
1481 // nsIRunnablePriority::PRIORITY_* to SetTaskPriority.
1482 void SetTaskPriority(uint32_t aPriority, const char* aSite) {
1483 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1484 mMagic3 == sMagic && mMagic4 == &mMutex);
1485 MutexAutoLock lock(mMutex);
1486 PROMISE_LOG("%s TaskPriority MozPromise (%p created at %s)", aSite, this,
1487 mCreationSite.get());
1488 MOZ_ASSERT(IsPending(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1490
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1489 "A Promise must not have been already resolved or rejected to "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1490
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1490 "set dispatch state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1490
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1491 MOZ_ASSERT(!mUseSynchronousTaskDispatch,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mUseSynchronousTaskDispatch)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mUseSynchronousTaskDispatch
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mUseSynchronousTaskDispatch" " (" "Promise already set for synchronous dispatch"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1492); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseSynchronousTaskDispatch"
") (" "Promise already set for synchronous dispatch" ")"); do
{ MOZ_CrashSequence(__null, 1492); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1492 "Promise already set for synchronous dispatch")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mUseSynchronousTaskDispatch)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mUseSynchronousTaskDispatch
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mUseSynchronousTaskDispatch" " (" "Promise already set for synchronous dispatch"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1492); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseSynchronousTaskDispatch"
") (" "Promise already set for synchronous dispatch" ")"); do
{ MOZ_CrashSequence(__null, 1492); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1493 MOZ_ASSERT(!mUseDirectTaskDispatch,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mUseDirectTaskDispatch)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mUseDirectTaskDispatch))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mUseDirectTaskDispatch"
" (" "Promise already set for direct dispatch" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseDirectTaskDispatch"
") (" "Promise already set for direct dispatch" ")"); do { MOZ_CrashSequence
(__null, 1494); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1494 "Promise already set for direct dispatch")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mUseDirectTaskDispatch)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mUseDirectTaskDispatch))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mUseDirectTaskDispatch"
" (" "Promise already set for direct dispatch" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseDirectTaskDispatch"
") (" "Promise already set for direct dispatch" ")"); do { MOZ_CrashSequence
(__null, 1494); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1495 mPriority = aPriority;
1496 }
1497
1498 private:
1499 template <typename, typename>
1500 friend class MozPromiseHolderBase;
1501
1502 // See MozPromiseHolderBase::RequireTailDispatch().
1503 void RequireTailDispatch(const char* aSite) {
1504#ifdef DEBUG1
1505 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1506 mMagic3 == sMagic && mMagic4 == &mMutex);
1507 MutexAutoLock lock(mMutex);
1508 PROMISE_LOG("%s RequireTailDispatch MozPromise (%p created at %s)", aSite,
1509 this, mCreationSite.get());
1510 MOZ_ASSERT(IsPending(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1512
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1511 "A Promise must not have been already resolved or rejected to "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1512
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1512 "set dispatch state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPending()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsPending()" " ("
"A Promise must not have been already resolved or rejected to "
"set dispatch state" ")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1512
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1513 mRequireTailDispatch = true;
1514#endif
1515 }
1516};
1517
1518// A generic promise type that does the trick for simple use cases.
1519//
1520// Vaguely deprecated: prefer explicitly naming the resolve- and reject-type.
1521// Additionally, prefer `mozilla::Ok` as the resolve-type if the boolean's value
1522// is irrelevant.
1523using GenericPromise = MozPromise<bool, nsresult, /* IsExclusive = */ true>;
1524
1525// A generic, non-exclusive promise type that does the trick for simple use
1526// cases.
1527//
1528// Vaguely deprecated, as above.
1529using GenericNonExclusivePromise =
1530 MozPromise<bool, nsresult, /* IsExclusive = */ false>;
1531
1532/*
1533 * Class to encapsulate a promise for a particular role. Use this as the member
1534 * variable for a class whose method returns a promise.
1535 */
1536template <typename PromiseType, typename ImplType>
1537class MozPromiseHolderBase {
1538 public:
1539 MozPromiseHolderBase() = default;
1540
1541 MozPromiseHolderBase(MozPromiseHolderBase&& aOther) noexcept = default;
1542 MozPromiseHolderBase& operator=(MozPromiseHolderBase&& aOther) noexcept =
1543 default;
1544
1545 ~MozPromiseHolderBase() { MOZ_ASSERT(!mPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mPromise", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPromise" ")"
); do { MOZ_CrashSequence(__null, 1545); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; }
1546
1547 already_AddRefed<PromiseType> Ensure(StaticString aMethodName) {
1548 static_cast<ImplType*>(this)->Check();
1549 if (!mPromise) {
1550 mPromise = new (typename PromiseType::Private)(aMethodName);
1551 }
1552 RefPtr<PromiseType> p = mPromise.get();
1553 return p.forget();
1554 }
1555
1556 bool IsEmpty() const {
1557 static_cast<const ImplType*>(this)->Check();
1558 return !mPromise;
1559 }
1560
1561 already_AddRefed<typename PromiseType::Private> Steal() {
1562 static_cast<ImplType*>(this)->Check();
1563 return mPromise.forget();
1564 }
1565
1566 template <typename ResolveValueType_>
1567 void Resolve(ResolveValueType_&& aResolveValue, StaticString aMethodName) {
1568 static_assert(std::is_convertible_v<ResolveValueType_,
1569 typename PromiseType::ResolveValueType>,
1570 "Resolve() argument must be implicitly convertible to "
1571 "MozPromise's ResolveValueT");
1572
1573 static_cast<ImplType*>(this)->Check();
1574 MOZ_ASSERT(mPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPromise", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1575 mPromise->Resolve(std::forward<ResolveValueType_>(aResolveValue),
1576 aMethodName);
1577 mPromise = nullptr;
1578 }
1579
1580 template <typename ResolveValueType_>
1581 void ResolveIfExists(ResolveValueType_&& aResolveValue,
1582 StaticString aMethodName) {
1583 if (!IsEmpty()) {
1584 Resolve(std::forward<ResolveValueType_>(aResolveValue), aMethodName);
1585 }
1586 }
1587
1588 template <typename RejectValueType_>
1589 void Reject(RejectValueType_&& aRejectValue, StaticString aMethodName) {
1590 static_assert(std::is_convertible_v<RejectValueType_,
1591 typename PromiseType::RejectValueType>,
1592 "Reject() argument must be implicitly convertible to "
1593 "MozPromise's RejectValueT");
1594
1595 static_cast<ImplType*>(this)->Check();
1596 MOZ_ASSERT(mPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPromise", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1596); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1596); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1597 mPromise->Reject(std::forward<RejectValueType_>(aRejectValue), aMethodName);
1598 mPromise = nullptr;
1599 }
1600
1601 template <typename RejectValueType_>
1602 void RejectIfExists(RejectValueType_&& aRejectValue,
1603 StaticString aMethodName) {
1604 if (!IsEmpty()) {
1605 Reject(std::forward<RejectValueType_>(aRejectValue), aMethodName);
1606 }
1607 }
1608
1609 template <typename ResolveOrRejectValueType_>
1610 void ResolveOrReject(ResolveOrRejectValueType_&& aValue,
1611 StaticString aMethodName) {
1612 static_cast<ImplType*>(this)->Check();
1613 MOZ_ASSERT(mPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPromise", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1613); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1613); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1614 mPromise->ResolveOrReject(std::forward<ResolveOrRejectValueType_>(aValue),
1615 aMethodName);
1616 mPromise = nullptr;
1617 }
1618
1619 template <typename ResolveOrRejectValueType_>
1620 void ResolveOrRejectIfExists(ResolveOrRejectValueType_&& aValue,
1621 StaticString aMethodName) {
1622 if (!IsEmpty()) {
1623 ResolveOrReject(std::forward<ResolveOrRejectValueType_>(aValue),
1624 aMethodName);
1625 }
1626 }
1627
1628 void UseSynchronousTaskDispatch(const char* aSite) {
1629 MOZ_ASSERT(mPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPromise", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1629); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1630 mPromise->UseSynchronousTaskDispatch(aSite);
1631 }
1632
1633 void UseDirectTaskDispatch(const char* aSite) {
1634 MOZ_ASSERT(mPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPromise", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1634); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1635 mPromise->UseDirectTaskDispatch(aSite);
1636 }
1637
1638 void SetTaskPriority(uint32_t aPriority, const char* aSite) {
1639 MOZ_ASSERT(mPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPromise", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1639); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1640 mPromise->SetTaskPriority(aPriority, aSite);
1641 }
1642
1643 // Require the event target of each Then() on the promise to support tail
1644 // dispatch, see nsIEventTarget::SUPPORTS_TAIL_DISPATCH, so that a producer
1645 // settling the promise from a tail dispatching AbstractThread only queues the
1646 // resolve/reject callbacks on its tail dispatcher. Asserted in debug builds
1647 // when the callbacks are dispatched. UseSynchronousTaskDispatch() and
1648 // UseDirectTaskDispatch() take precedence for same-thread targets.
1649 void RequireTailDispatch(const char* aSite) {
1650 MOZ_ASSERT(mPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPromise", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1650); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1651 mPromise->RequireTailDispatch(aSite);
1652 }
1653
1654 private:
1655 RefPtr<typename PromiseType::Private> mPromise;
1656};
1657
1658template <typename PromiseType>
1659class MozPromiseHolder
1660 : public MozPromiseHolderBase<PromiseType, MozPromiseHolder<PromiseType>> {
1661 public:
1662 using MozPromiseHolderBase<
1663 PromiseType, MozPromiseHolder<PromiseType>>::MozPromiseHolderBase;
1664 static constexpr void Check() {};
1665};
1666
1667template <typename PromiseType>
1668class MozMonitoredPromiseHolder
1669 : public MozPromiseHolderBase<PromiseType,
1670 MozMonitoredPromiseHolder<PromiseType>> {
1671 public:
1672 // Provide a Monitor that should always be held when accessing this instance.
1673 explicit MozMonitoredPromiseHolder(Monitor* const aMonitor)
1674 : mMonitor(aMonitor) {
1675 MOZ_ASSERT(aMonitor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMonitor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMonitor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aMonitor", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMonitor" ")"
); do { MOZ_CrashSequence(__null, 1675); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1676 }
1677
1678 MozMonitoredPromiseHolder(MozMonitoredPromiseHolder&& aOther) = delete;
1679 MozMonitoredPromiseHolder& operator=(MozMonitoredPromiseHolder&& aOther) =
1680 delete;
1681
1682 void Check() const { mMonitor->AssertCurrentThreadOwns(); }
1683
1684 private:
1685 Monitor* const mMonitor;
1686};
1687
1688/*
1689 * Class to encapsulate a MozPromise::Request reference. Use this as the member
1690 * variable for a class waiting on a MozPromise.
1691 */
1692template <typename PromiseType>
1693class MozPromiseRequestHolder {
1694 public:
1695 MozPromiseRequestHolder() = default;
1696 ~MozPromiseRequestHolder() { MOZ_ASSERT(!mRequest)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRequest))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mRequest", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRequest" ")"
); do { MOZ_CrashSequence(__null, 1696); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; }
1697
1698 void Track(already_AddRefed<typename PromiseType::Request> aRequest) {
1699 MOZ_DIAGNOSTIC_ASSERT(!Exists())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!Exists())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!Exists()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!Exists()", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1699); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!Exists()"
")"); do { MOZ_CrashSequence(__null, 1699); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1700 mRequest = aRequest;
1701 }
1702
1703 void Complete() {
1704 MOZ_DIAGNOSTIC_ASSERT(Exists())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(Exists())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(Exists()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("Exists()", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1704); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "Exists()"
")"); do { MOZ_CrashSequence(__null, 1704); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1705 mRequest = nullptr;
1706 }
1707
1708 // Disconnects and forgets an outstanding promise. The resolve/reject methods
1709 // will never be called.
1710 void Disconnect() {
1711 MOZ_ASSERT(Exists())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(Exists())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(Exists()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("Exists()", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Exists()" ")"
); do { MOZ_CrashSequence(__null, 1711); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1712 RefPtr request = std::move(mRequest);
1713 request->Disconnect();
1714 }
1715
1716 void DisconnectIfExists() {
1717 if (Exists()) {
1718 Disconnect();
1719 }
1720 }
1721
1722 bool Exists() const { return !!mRequest; }
1723
1724 private:
1725 RefPtr<typename PromiseType::Request> mRequest;
1726};
1727
1728// Asynchronous Potentially-Cross-Thread Method Calls.
1729//
1730// This machinery allows callers to schedule a promise-returning function
1731// (a method and object, or a function object like a lambda) to be invoked
1732// asynchronously on a given thread, while at the same time receiving a
1733// promise upon which to invoke Then() immediately. InvokeAsync dispatches a
1734// task to invoke the function on the proper thread and also chain the
1735// resulting promise to the one that the caller received, so that resolve/
1736// reject values are forwarded through.
1737
1738namespace detail {
1739
1740// Non-templated base class to allow us to use MOZ_COUNT_{C,D}TOR, which cause
1741// assertions when used on templated types.
1742class MethodCallBase {
1743 public:
1744 MOZ_COUNTED_DEFAULT_CTOR(MethodCallBase)MethodCallBase() { do { static_assert(std::is_class_v<MethodCallBase
>, "Token '" "MethodCallBase" "' is not a class type."); static_assert
(!std::is_base_of_v<nsISupports, MethodCallBase>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "MethodCallBase"
, sizeof(*this)); } while (0); }
1745 MOZ_COUNTED_DTOR_VIRTUAL(MethodCallBase)virtual ~MethodCallBase() { do { static_assert(std::is_class_v
<MethodCallBase>, "Token '" "MethodCallBase" "' is not a class type."
); static_assert(!std::is_base_of_v<nsISupports, MethodCallBase
>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "MethodCallBase"
, sizeof(*this)); } while (0); }
1746};
1747
1748template <typename PromiseType, typename MethodType, typename ThisType,
1749 typename... Storages>
1750class MethodCall : public MethodCallBase {
1751 public:
1752 template <typename... Args>
1753 MethodCall(MethodType aMethod, ThisType* aThisVal, Args&&... aArgs)
1754 : mMethod(aMethod),
1755 mThisVal(aThisVal),
1756 mArgs(std::forward<Args>(aArgs)...) {
1757 static_assert(sizeof...(Storages) == sizeof...(Args),
1758 "Storages and Args should have equal sizes");
1759 }
1760
1761 RefPtr<PromiseType> Invoke() { return mArgs.apply(mThisVal.get(), mMethod); }
1762
1763 private:
1764 MethodType mMethod;
1765 RefPtr<ThisType> mThisVal;
1766 RunnableMethodArguments<Storages...> mArgs;
1767};
1768
1769template <typename PromiseType, typename MethodType, typename ThisType,
1770 typename... Storages>
1771class ProxyRunnable : public CancelableRunnable {
1772 public:
1773 ProxyRunnable(
1774 typename PromiseType::Private* aProxyPromise,
1775 MethodCall<PromiseType, MethodType, ThisType, Storages...>* aMethodCall)
1776 : CancelableRunnable("detail::ProxyRunnable"),
1777 mProxyPromise(aProxyPromise),
1778 mMethodCall(aMethodCall) {}
1779
1780 NS_IMETHODvirtual nsresult Run() override {
1781 RefPtr<PromiseType> p = mMethodCall->Invoke();
1782 mMethodCall = nullptr;
1783 p->ChainTo(mProxyPromise.forget(), "<Proxy Promise>");
1784 return NS_OK;
1785 }
1786
1787 nsresult Cancel() override { return Run(); }
1788
1789 private:
1790 RefPtr<typename PromiseType::Private> mProxyPromise;
1791 UniquePtr<MethodCall<PromiseType, MethodType, ThisType, Storages...>>
1792 mMethodCall;
1793};
1794
1795template <typename... Storages, typename PromiseType, typename ThisType,
1796 typename... ArgTypes, typename... ActualArgTypes>
1797RefPtr<PromiseType> InvokeAsyncImpl(
1798 nsISerialEventTarget* aTarget, ThisType* aThisVal, StaticString aCallerName,
1799 RefPtr<PromiseType> (ThisType::*aMethod)(ArgTypes...),
1800 ActualArgTypes&&... aArgs) {
1801 MOZ_ASSERT(aTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTarget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTarget", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTarget" ")"
); do { MOZ_CrashSequence(__null, 1801); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1802
1803 typedef RefPtr<PromiseType> (ThisType::*MethodType)(ArgTypes...);
1804 typedef detail::MethodCall<PromiseType, MethodType, ThisType, Storages...>
1805 MethodCallType;
1806 typedef detail::ProxyRunnable<PromiseType, MethodType, ThisType, Storages...>
1807 ProxyRunnableType;
1808
1809 MethodCallType* methodCall = new MethodCallType(
1810 aMethod, aThisVal, std::forward<ActualArgTypes>(aArgs)...);
1811 RefPtr<typename PromiseType::Private> p =
1812 new (typename PromiseType::Private)(aCallerName);
1813 RefPtr<ProxyRunnableType> r = new ProxyRunnableType(p, methodCall);
1814 aTarget->Dispatch(r.forget());
1815 return p;
1816}
1817
1818constexpr bool Any() { return false; }
1819
1820template <typename T1>
1821constexpr bool Any(T1 a) {
1822 return static_cast<bool>(a);
1823}
1824
1825template <typename T1, typename... Ts>
1826constexpr bool Any(T1 a, Ts... aOthers) {
1827 return a || Any(aOthers...);
1828}
1829
1830} // namespace detail
1831
1832// InvokeAsync with explicitly-specified storages.
1833// See ParameterStorage in nsThreadUtils.h for help.
1834template <typename... Storages, typename PromiseType, typename ThisType,
1835 typename... ArgTypes, typename... ActualArgTypes,
1836 std::enable_if_t<sizeof...(Storages) != 0, int> = 0>
1837RefPtr<PromiseType> InvokeAsync(
1838 nsISerialEventTarget* aTarget, ThisType* aThisVal, StaticString aCallerName,
1839 RefPtr<PromiseType> (ThisType::*aMethod)(ArgTypes...),
1840 ActualArgTypes&&... aArgs) {
1841 static_assert(
1842 sizeof...(Storages) == sizeof...(ArgTypes),
1843 "Provided Storages and method's ArgTypes should have equal sizes");
1844 static_assert(sizeof...(Storages) == sizeof...(ActualArgTypes),
1845 "Provided Storages and ActualArgTypes should have equal sizes");
1846 return detail::InvokeAsyncImpl<Storages...>(
1847 aTarget, aThisVal, aCallerName, aMethod,
1848 std::forward<ActualArgTypes>(aArgs)...);
1849}
1850
1851// InvokeAsync with no explicitly-specified storages, will copy arguments and
1852// then move them out of the runnable into the target method parameters.
1853template <typename... Storages, typename PromiseType, typename ThisType,
1854 typename... ArgTypes, typename... ActualArgTypes,
1855 std::enable_if_t<sizeof...(Storages) == 0, int> = 0>
1856RefPtr<PromiseType> InvokeAsync(
1857 nsISerialEventTarget* aTarget, ThisType* aThisVal, StaticString aCallerName,
1858 RefPtr<PromiseType> (ThisType::*aMethod)(ArgTypes...),
1859 ActualArgTypes&&... aArgs) {
1860 static_assert(
1861 !detail::Any(
1862 std::is_pointer_v<std::remove_reference_t<ActualArgTypes>>...),
1863 "Cannot pass pointer types through InvokeAsync, Storages must be "
1864 "provided");
1865 static_assert(sizeof...(ArgTypes) == sizeof...(ActualArgTypes),
1866 "Method's ArgTypes and ActualArgTypes should have equal sizes");
1867 return detail::InvokeAsyncImpl<
1868 StoreCopyPassByRRef<std::decay_t<ActualArgTypes>>...>(
1869 aTarget, aThisVal, aCallerName, aMethod,
1870 std::forward<ActualArgTypes>(aArgs)...);
1871}
1872
1873namespace detail {
1874
1875template <typename Function, typename PromiseType>
1876class ProxyFunctionRunnable : public CancelableRunnable {
1877 using FunctionStorage = std::decay_t<Function>;
1878
1879 public:
1880 template <typename F>
1881 ProxyFunctionRunnable(typename PromiseType::Private* aProxyPromise,
1882 F&& aFunction)
1883 : CancelableRunnable("detail::ProxyFunctionRunnable"),
1884 mProxyPromise(aProxyPromise),
1885 mFunction(new FunctionStorage(std::forward<F>(aFunction))) {}
1886
1887 NS_IMETHODvirtual nsresult Run() override {
1888 RefPtr<PromiseType> p = (*mFunction)();
1889 mFunction = nullptr;
1890 p->ChainTo(mProxyPromise.forget(), "<Proxy Promise>");
1891 return NS_OK;
1892 }
1893
1894 nsresult Cancel() override { return Run(); }
1895
1896 private:
1897 RefPtr<typename PromiseType::Private> mProxyPromise;
1898 UniquePtr<FunctionStorage> mFunction;
1899};
1900
1901template <typename T>
1902constexpr static bool IsRefPtrMozPromise = false;
1903template <typename T, typename U, bool B>
1904constexpr static bool IsRefPtrMozPromise<RefPtr<MozPromise<T, U, B>>> = true;
1905
1906} // namespace detail
1907
1908// Invoke a function object (e.g., lambda) asynchronously.
1909// Return a promise that the function should eventually resolve or reject.
1910template <typename Function>
1911auto InvokeAsync(nsISerialEventTarget* aTarget, StaticString aCallerName,
1912 Function&& aFunction) -> decltype(aFunction()) {
1913 static_assert(!std::is_lvalue_reference_v<Function>,
1914 "Function object must not be passed by lvalue-ref (to avoid "
1915 "unplanned copies); Consider move()ing the object.");
1916
1917 static_assert(detail::IsRefPtrMozPromise<decltype(aFunction())>,
1918 "Function object must return RefPtr<MozPromise>");
1919 MOZ_ASSERT(aTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTarget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTarget", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h"
, 1919); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTarget" ")"
); do { MOZ_CrashSequence(__null, 1919); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1920 typedef RemoveSmartPointer<decltype(aFunction())> PromiseType;
1921 typedef detail::ProxyFunctionRunnable<Function, PromiseType>
1922 ProxyRunnableType;
1923
1924 auto p = MakeRefPtr<typename PromiseType::Private>(aCallerName);
1925 auto r = MakeRefPtr<ProxyRunnableType>(p, std::forward<Function>(aFunction));
1926 aTarget->Dispatch(r.forget());
1927 return p;
1928}
1929
1930#undef PROMISE_LOG
1931#undef PROMISE_ASSERT
1932#undef PROMISE_DEBUG
1933
1934} // namespace mozilla
1935
1936#endif

←

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/cxxalloc.h

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#ifndef mozilla_cxxalloc_h
6#define mozilla_cxxalloc_h
7
8/*
9 * We implement the default operators new/delete as part of
10 * libmozalloc, replacing their definitions in libstdc++. The
11 * operator new* definitions in libmozalloc will never return a NULL
12 * pointer.
13 *
14 * Each operator new immediately below returns a pointer to memory
15 * that can be delete'd by any of
16 *
17 * (1) the matching infallible operator delete immediately below
18 * (2) the matching system |operator delete(void*, std::nothrow)|
19 * (3) the matching system |operator delete(void*) noexcept(false)|
20 *
21 * NB: these are declared |noexcept(false)|, though they will never
22 * throw that exception. This declaration is consistent with the rule
23 * that |::operator new() noexcept(false)| will never return NULL.
24 *
25 * NB: mozilla::fallible can be used instead of std::nothrow.
26 */
27
28#ifndef MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline
29# define MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline MFBT_API__attribute__((weak)) __attribute__((visibility("default")))
30#endif
31
32MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new(size_t size) noexcept(false) {
33 return moz_xmalloc(size);
34}
35
36MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new(size_t size,
37 const std::nothrow_t&) noexcept(true) {
38 return malloc_implmalloc(size);
39}
40
41MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new[](size_t size) noexcept(false) {
42 return moz_xmalloc(size);
43}
44
45// Inlining `new` like this is technically against C++ spec, but we crave perf.
46MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new[](size_t size,
47 const std::nothrow_t&) noexcept(true) {
48#if defined(__GNUC__4) && !defined(__clang__1)
49// GCC-14 codegen at -O2 causes false positive due to converting
50// `new A[n]` to `malloc(-1)` when `n > PTRDIFF_MAX/sizeof(A)`.
51// (See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85783, WONTFIX'd)
52# pragma GCC diagnostic push
53# pragma GCC diagnostic ignored "-Walloc-size-larger-than="
54#endif
55
56 return malloc_implmalloc(size);
57
58#if defined(__GNUC__4) && !defined(__clang__1)
59# pragma GCC diagnostic pop
60#endif
61}
62
63MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr) noexcept(true) {
64 return free_implfree(ptr);
25
Memory is released
65}
66
67MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
68 const std::nothrow_t&) noexcept(true) {
69 return free_implfree(ptr);
70}
71
72MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr) noexcept(true) {
73 return free_implfree(ptr);
74}
75
76MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](
77 void* ptr, const std::nothrow_t&) noexcept(true) {
78 return free_implfree(ptr);
79}
80
81#if defined(XP_WIN)
82// We provide the global sized delete overloads unconditionally because the
83// MSVC runtime headers do, despite compiling with /Zc:sizedDealloc-
84MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
85 size_t /*size*/) noexcept(true) {
86 return free_implfree(ptr);
87}
88
89MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr,
90 size_t /*size*/) noexcept(true) {
91 return free_implfree(ptr);
92}
93#endif
94
95#endif /* mozilla_cxxalloc_h */