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