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-01-224014-2642839-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// Used for protecting codec support information collected from different remote
80// processes.
81StaticMutex sProcessSupportedMutex;
82MOZ_GLOBINIT static EnumeratedArray<RemoteMediaIn,
83 Maybe<media::MediaCodecsSupported>,
84 size_t(RemoteMediaIn::SENTINEL)>
85 sProcessSupported MOZ_GUARDED_BY(sProcessSupportedMutex)__attribute__((guarded_by(sProcessSupportedMutex)));
86
87class ShutdownObserver final : public nsIObserver {
88 public:
89 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:
90 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
91
92 protected:
93 ~ShutdownObserver() = default;
94};
95NS_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"
, 95); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 95
); __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"
, 95); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShutdownObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 95); __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"
, 95); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 95)
; __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"
, 95); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShutdownObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 95); __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"
, 95); 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; }
;
96
97NS_IMETHODIMPnsresult
98ShutdownObserver::Observe(nsISupports* aSubject, const char* aTopic,
99 const char16_t* aData) {
100 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"
, 100); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!strcmp(aTopic, \"xpcom-shutdown\")"
")"); do { MOZ_CrashSequence(__null, 100); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
101 RemoteMediaManagerChild::Shutdown();
102 return NS_OK;
103}
104
105StaticRefPtr<ShutdownObserver> sObserver;
106
107/* static */
108void RemoteMediaManagerChild::Init() {
109 LOG("RemoteMediaManagerChild Init");
110
111 auto remoteDecoderManagerThread = sRemoteMediaManagerChildThread.Lock();
112 if (!*remoteDecoderManagerThread) {
113 LOG("RemoteMediaManagerChild's thread is created");
114 // We can't use a MediaThreadType::SUPERVISOR as the RemoteDecoderModule
115 // runs on it and dispatch synchronous tasks to the manager thread, should
116 // more than 4 concurrent videos being instantiated at the same time, we
117 // could end up in a deadlock.
118 RefPtr<nsIThread> childThread;
119 nsresult rv = NS_NewNamedThread(
120 "RemVidChild", getter_AddRefs(childThread),
121 NS_NewRunnableFunction(
122 "RemoteMediaManagerChild::InitPBackground", []() {
123 ipc::PBackgroundChild* bgActor =
124 ipc::BackgroundChild::GetOrCreateForCurrentThread();
125 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"
, 126); } } while (false)
126 "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"
, 126); } } while (false)
;
127 (void)bgActor;
128 }));
129
130 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"
, 130); return; } } while (false)
;
131 *remoteDecoderManagerThread = childThread;
132 sRecreateTasks = new nsTArray<RefPtr<Runnable>>();
133 sObserver = new ShutdownObserver();
134 nsContentUtils::RegisterShutdownObserver(sObserver);
135 }
136}
137
138/* static */
139void RemoteMediaManagerChild::InitForGPUProcess(
140 Endpoint<PRemoteMediaManagerChild>&& aVideoManager) {
141 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"
, 141); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 141); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
142
143 Init();
144
145 auto remoteDecoderManagerThread = sRemoteMediaManagerChildThread.Lock();
146 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"
, 150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
147 (*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"
, 150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
148 ->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"
, 150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
149 "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"
, 150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
150 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"
, 150); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED((*remoteDecoderManagerThread) ->Dispatch(NewRunnableFunction( \"InitForContentRunnable\", &OpenRemoteMediaManagerChildForProcess, std::move(aVideoManager), RemoteMediaIn::GpuProcess)))"
")"); do { MOZ_CrashSequence(__null, 150); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
151}
152
153/* static */
154void RemoteMediaManagerChild::Shutdown() {
155 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"
, 155); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 155); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
156 LOG("RemoteMediaManagerChild Shutdown");
157
158 if (sObserver) {
159 nsContentUtils::UnregisterShutdownObserver(sObserver);
160 sObserver = nullptr;
161 }
162
163 nsCOMPtr<nsIThread> childThread;
164 {
165 auto remoteDecoderManagerThread = sRemoteMediaManagerChildThread.Lock();
166 childThread = remoteDecoderManagerThread->forget();
167 LOG("RemoteMediaManagerChild's thread is released");
168 }
169 if (childThread) {
170 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
171 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
172 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
173 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
174 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
175 }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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
176 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
177 }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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
178 {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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
179 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
180 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
181 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
182 }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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
183 }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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
184 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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
185 })))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"
, 185); 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, 185); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
186 childThread->Shutdown();
187 sRecreateTasks = nullptr;
188 }
189}
190
191/* static */ void RemoteMediaManagerChild::RunWhenGPUProcessRecreated(
192 const RemoteMediaManagerChild* aDyingManager,
193 already_AddRefed<Runnable> aTask) {
194 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
195 if (!managerThread) {
196 // We've been shutdown, bail.
197 return;
198 }
199 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"
, 199); AnnotateMozCrashReason("MOZ_ASSERT" "(" "managerThread->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 199); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
200
201 // If we've already been recreated, then run the task immediately.
202 auto* manager = GetSingleton(RemoteMediaIn::GpuProcess);
203 if (manager && manager != aDyingManager && manager->CanSend()) {
204 RefPtr<Runnable> task = aTask;
205 task->Run();
206 } else {
207 sRecreateTasks->AppendElement(aTask);
208 }
209}
210
211/* static */
212RemoteMediaManagerChild* RemoteMediaManagerChild::GetSingleton(
213 RemoteMediaIn aLocation) {
214 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
215 if (!managerThread) {
216 // We've been shutdown, bail.
217 return nullptr;
218 }
219 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"
, 219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "managerThread->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 219); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
220 switch (aLocation) {
221 case RemoteMediaIn::GpuProcess:
222 case RemoteMediaIn::RddProcess:
223 case RemoteMediaIn::UtilityProcess_Generic:
224 case RemoteMediaIn::UtilityProcess_AppleMedia:
225 case RemoteMediaIn::UtilityProcess_WMF:
226 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM:
227 return sRemoteMediaManagerChildForProcesses[aLocation];
228 default:
229 MOZ_CRASH("Unexpected RemoteMediaIn variant")do { do { } while (false); MOZ_ReportCrash("" "Unexpected RemoteMediaIn variant"
, "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 229); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected RemoteMediaIn variant"
")"); do { MOZ_CrashSequence(__null, 229); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
230 return nullptr;
231 }
232}
233
234/* static */
235nsCOMPtr<nsISerialEventTarget> RemoteMediaManagerChild::GetManagerThread() {
236 auto remoteDecoderManagerThread = sRemoteMediaManagerChildThread.Lock();
237 return nsCOMPtr<nsISerialEventTarget>(*remoteDecoderManagerThread);
238}
239
240/* static */
241media::DecodeSupportSet RemoteMediaManagerChild::Supports(
242 RemoteMediaIn aLocation, const SupportDecoderParams& aParams,
243 DecoderDoctorDiagnostics* aDiagnostics) {
244 Maybe<media::MediaCodecsSupported> supported;
245 switch (aLocation) {
246 case RemoteMediaIn::GpuProcess:
247 case RemoteMediaIn::RddProcess:
248 case RemoteMediaIn::UtilityProcess_AppleMedia:
249 case RemoteMediaIn::UtilityProcess_Generic:
250 case RemoteMediaIn::UtilityProcess_WMF:
251 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM: {
252 StaticMutexAutoLock lock(sProcessSupportedMutex);
253 supported = sProcessSupported[aLocation];
254 break;
255 }
256 default:
257 return {};
258 }
259 if (!supported) {
260 // We haven't received the correct information yet from either the GPU or
261 // the RDD process nor the Utility process.
262 if (aLocation == RemoteMediaIn::UtilityProcess_Generic ||
263 aLocation == RemoteMediaIn::UtilityProcess_AppleMedia ||
264 aLocation == RemoteMediaIn::UtilityProcess_WMF ||
265 aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
266 LaunchUtilityProcessIfNeeded(aLocation);
267 }
268 if (aLocation == RemoteMediaIn::RddProcess) {
269 // Ensure the RDD process got started.
270 // TODO: This can be removed once bug 1684991 is fixed.
271 LaunchRDDProcessIfNeeded();
272 }
273
274 // Assume the format is supported to prevent false negative, if the remote
275 // process supports that specific track type. HW support is unknown until
276 // the process reports in, so conservatively report SW-only.
277 const bool isVideo = aParams.mConfig.IsVideo();
278 const bool isAudio = aParams.mConfig.IsAudio();
279 const auto trackSupport = GetTrackSupport(aLocation);
280 if (isVideo) {
281 // Special condition for HEVC, which can only be supported in specific
282 // process. As HEVC support is still a experimental feature, we don't want
283 // to report support for it arbitrarily.
284 if (MP4Decoder::IsHEVC(aParams.mConfig.mMimeType)) {
285 if (!StaticPrefs::media_hevc_enabled()) {
286 return {};
287 }
288#if defined(XP_WIN)
289 if (aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM ||
290 aLocation == RemoteMediaIn::GpuProcess) {
291 // No software support in most cases for HEVC so guess hardware.
292 return {media::DecodeSupport::HardwareDecode};
293 }
294 return {};
295#else
296 return trackSupport.contains(TrackSupport::DecodeVideo)
297 ? media::
298 DecodeSupportSet{media::DecodeSupport::SoftwareDecode}
299 : media::DecodeSupportSet{};
300#endif
301 }
302 return trackSupport.contains(TrackSupport::DecodeVideo)
303 ? media::DecodeSupportSet{media::DecodeSupport::SoftwareDecode}
304 : media::DecodeSupportSet{};
305 }
306 if (isAudio) {
307 return trackSupport.contains(TrackSupport::DecodeAudio)
308 ? media::DecodeSupportSet{media::DecodeSupport::SoftwareDecode}
309 : media::DecodeSupportSet{};
310 }
311 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"
, 311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Not audio and video?!" ")"); do {
MOZ_CrashSequence(__null, 311); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
312 return {};
313 }
314
315 // We can ignore the SupportDecoderParams argument for now as creation of the
316 // decoder will actually fail later and fallback PDMs will be tested on later.
317 return PDMFactory::SupportsMimeType(aParams.MimeType(), *supported,
318 aLocation);
319}
320
321/* static */
322RefPtr<PlatformDecoderModule::CreateDecoderPromise>
323RemoteMediaManagerChild::CreateAudioDecoder(const CreateDecoderParams& aParams,
324 RemoteMediaIn aLocation) {
325 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
326 if (!managerThread) {
327 // We got shutdown.
328 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
329 NS_ERROR_DOM_MEDIA_CANCELED, __func__);
330 }
331
332 if (!GetTrackSupport(aLocation).contains(TrackSupport::DecodeAudio)) {
333 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
334 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
335 nsPrintfCString("%s doesn't support audio decoding",
336 RemoteMediaInToStr(aLocation))
337 .get()),
338 __func__);
339 }
340
341 if (!aParams.mMediaEngineId &&
342 aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
343 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
344 MediaResult(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR,
345 nsPrintfCString("%s only support for media engine playback",
346 RemoteMediaInToStr(aLocation))
347 .get()),
348 __func__);
349 }
350
351 RefPtr<GenericNonExclusivePromise> launchPromise;
352 if (StaticPrefs::media_utility_process_enabled() &&
353 (aLocation == RemoteMediaIn::UtilityProcess_Generic ||
354 aLocation == RemoteMediaIn::UtilityProcess_AppleMedia ||
355 aLocation == RemoteMediaIn::UtilityProcess_WMF)) {
356 launchPromise = LaunchUtilityProcessIfNeeded(aLocation);
357 } else if (aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
358 launchPromise = LaunchUtilityProcessIfNeeded(aLocation);
359 } else if (StaticPrefs::media_allow_audio_non_utility() || aParams.mCDM) {
360 launchPromise = LaunchRDDProcessIfNeeded();
361 } else {
362 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
363 MediaResult(
364 NS_ERROR_DOM_MEDIA_DENIED_IN_NON_UTILITY,
365 nsPrintfCString("%s is not allowed to perform audio decoding",
366 RemoteMediaInToStr(aLocation))
367 .get()),
368 __func__);
369 }
370 LOG("Create audio decoder in {}", RemoteMediaInToStr(aLocation));
371
372 return launchPromise->Then(
373 managerThread, __func__,
374 [params = CreateDecoderParamsForAsync(aParams), aLocation](bool) mutable {
375 auto child = MakeRefPtr<RemoteAudioDecoderChild>(aLocation);
376 MediaResult result =
377 child->InitIPDL(params.AudioConfig(), params.mOptions,
378 params.mMediaEngineId, params.mCDM);
379 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0)))) {
380 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
381 result, __func__);
382 }
383 return Construct(std::move(child), std::move(params), aLocation);
384 },
385 [aLocation](nsresult aResult) {
386 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
387 MediaResult(aResult,
388 aLocation == RemoteMediaIn::GpuProcess
389 ? "Couldn't start GPU process"
390 : (aLocation == RemoteMediaIn::RddProcess
391 ? "Couldn't start RDD process"
392 : "Couldn't start Utility process")),
393 __func__);
394 });
395}
396
397/* static */
398RefPtr<PlatformDecoderModule::CreateDecoderPromise>
399RemoteMediaManagerChild::CreateVideoDecoder(const CreateDecoderParams& aParams,
400 RemoteMediaIn aLocation) {
401 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
402 if (!managerThread) {
403 // We got shutdown.
404 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
405 NS_ERROR_DOM_MEDIA_CANCELED, __func__);
406 }
407
408 if (!aParams.mKnowsCompositor && aLocation == RemoteMediaIn::GpuProcess) {
409 // We don't have an image bridge; don't attempt to decode in the GPU
410 // process.
411 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
412 NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR, __func__);
413 }
414
415 if (!GetTrackSupport(aLocation).contains(TrackSupport::DecodeVideo)) {
416 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
417 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
418 nsPrintfCString("%s doesn't support video decoding",
419 RemoteMediaInToStr(aLocation))
420 .get()),
421 __func__);
422 }
423
424 if (!aParams.mMediaEngineId &&
425 aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
426 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
427 MediaResult(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR,
428 nsPrintfCString("%s only support for media engine playback",
429 RemoteMediaInToStr(aLocation))
430 .get()),
431 __func__);
432 }
433
434 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"
, 434); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation != RemoteMediaIn::Unspecified"
")"); do { MOZ_CrashSequence(__null, 434); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
435
436 RefPtr<GenericNonExclusivePromise> p;
437 if (aLocation == RemoteMediaIn::GpuProcess) {
438 p = GenericNonExclusivePromise::CreateAndResolve(true, __func__);
439 } else if (aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
440 p = LaunchUtilityProcessIfNeeded(aLocation);
441 } else {
442 p = LaunchRDDProcessIfNeeded();
443 }
444 LOG("Create video decoder in {}", RemoteMediaInToStr(aLocation));
445
446 return p->Then(
447 managerThread, __func__,
448 [aLocation, params = CreateDecoderParamsForAsync(aParams)](bool) mutable {
449 auto child = MakeRefPtr<RemoteVideoDecoderChild>(aLocation);
450 MediaResult result = child->InitIPDL(
451 params.VideoConfig(), params.mRate.mValue, params.mOptions,
452 params.mKnowsCompositor
453 ? Some(params.mKnowsCompositor->GetTextureFactoryIdentifier())
454 : Nothing(),
455 params.mMediaEngineId, params.mTrackingId, params.mCDM);
456 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0)))) {
457 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
458 result, __func__);
459 }
460 return Construct(std::move(child), std::move(params), aLocation);
461 },
462 [](nsresult aResult) {
463 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
464 MediaResult(aResult, "Couldn't start RDD process"), __func__);
465 });
466}
467
468/* static */
469RefPtr<RemoteCDMProxy> RemoteMediaManagerChild::CreateCDM(
470 RemoteMediaIn aLocation, dom::MediaKeys* aKeys, const nsAString& aKeySystem,
471 bool aDistinctiveIdentifierRequired, bool aPersistentStateRequired) {
472 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"
, 472); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 472); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
473
474 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"
, 474)
) {
475 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"
, 475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Cannot use CDM outside RDD process"
")"); do { MOZ_CrashSequence(__null, 475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
476 return nullptr;
477 }
478
479 if (!StaticPrefs::media_ffvpx_hw_enabled()) {
480 return nullptr;
481 }
482
483 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
484 if (!managerThread) {
485 // We got shutdown.
486 return nullptr;
487 }
488
489 if (!GetTrackSupport(aLocation).contains(TrackSupport::DecodeVideo)) {
490 return nullptr;
491 }
492
493 RefPtr<GenericNonExclusivePromise> p = LaunchRDDProcessIfNeeded();
494 LOG("Create CDM in {}", RemoteMediaInToStr(aLocation));
495
496 return MakeRefPtr<RemoteCDMProxy>(
497 std::move(managerThread), std::move(p), aLocation, aKeys, aKeySystem,
498 aDistinctiveIdentifierRequired, aPersistentStateRequired);
499}
500
501/* static */
502RefPtr<PlatformDecoderModule::CreateDecoderPromise>
503RemoteMediaManagerChild::Construct(RefPtr<RemoteDecoderChild>&& aChild,
504 CreateDecoderParamsForAsync&& aParams,
505 RemoteMediaIn aLocation) {
506 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
507 if (!managerThread) {
508 // We got shutdown.
509 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
510 NS_ERROR_DOM_MEDIA_CANCELED, __func__);
511 }
512 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"
, 512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "managerThread->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 512); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
513
514 RefPtr<PlatformDecoderModule::CreateDecoderPromise> p =
515 aChild->SendConstruct()->Then(
516 managerThread, __func__,
517 [child = std::move(aChild),
518 params = std::move(aParams)](MediaResult aResult) {
519 if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
520 // We will never get to use this remote decoder, tear it down.
521 child->DestroyIPDL();
522 return PlatformDecoderModule::CreateDecoderPromise::
523 CreateAndReject(aResult, __func__);
524 }
525 if (params.mCDM) {
526 if (auto* cdm = params.mCDM->AsRemoteCDMProxy()) {
527 return PlatformDecoderModule::CreateDecoderPromise::
528 CreateAndResolve(
529 MakeRefPtr<EMEMediaDataDecoderProxy>(
530 params,
531 MakeAndAddRef<RemoteMediaDataDecoder>(child), cdm),
532 __func__);
533 }
534 return PlatformDecoderModule::CreateDecoderPromise::
535 CreateAndReject(
536 NS_ERROR_DOM_MEDIA_CDM_PROXY_NOT_SUPPORTED_ERR, __func__);
537 }
538 return PlatformDecoderModule::CreateDecoderPromise::
539 CreateAndResolve(MakeRefPtr<RemoteMediaDataDecoder>(child),
540 __func__);
541 },
542 [aLocation](const mozilla::ipc::ResponseRejectReason& aReason) {
543 // The parent has died.
544 nsresult err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_UTILITY_ERR;
545 if (aLocation == RemoteMediaIn::GpuProcess ||
546 aLocation == RemoteMediaIn::RddProcess) {
547 err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_RDD_OR_GPU_ERR;
548 } else if (aLocation ==
549 RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
550 err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_MF_CDM_ERR;
551 }
552 return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
553 err, __func__);
554 });
555 return p;
556}
557
558/* static */
559EncodeSupportSet RemoteMediaManagerChild::Supports(RemoteMediaIn aLocation,
560 CodecType aCodec) {
561 Maybe<media::MediaCodecsSupported> supported;
562 switch (aLocation) {
563 case RemoteMediaIn::GpuProcess:
564 case RemoteMediaIn::RddProcess:
565 case RemoteMediaIn::UtilityProcess_AppleMedia:
566 case RemoteMediaIn::UtilityProcess_Generic:
567 case RemoteMediaIn::UtilityProcess_WMF:
568 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM: {
569 StaticMutexAutoLock lock(sProcessSupportedMutex);
570 supported = sProcessSupported[aLocation];
571 break;
572 }
573 default:
574 return EncodeSupportSet{};
575 }
576 if (!supported) {
577 // We haven't received the correct information yet from either the GPU or
578 // the RDD process nor the Utility process.
579 if (aLocation == RemoteMediaIn::UtilityProcess_Generic ||
580 aLocation == RemoteMediaIn::UtilityProcess_AppleMedia ||
581 aLocation == RemoteMediaIn::UtilityProcess_WMF ||
582 aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
583 LaunchUtilityProcessIfNeeded(aLocation);
584 }
585 if (aLocation == RemoteMediaIn::RddProcess) {
586 // Ensure the RDD process got started.
587 // TODO: This can be removed once bug 1684991 is fixed.
588 LaunchRDDProcessIfNeeded();
589 }
590
591 // Assume the format is supported to prevent false negative, if the remote
592 // process supports that specific track type.
593 const auto trackSupport = GetTrackSupport(aLocation);
594 if (IsVideo(aCodec)) {
595 // Special condition for HEVC, which can only be supported in specific
596 // process. As HEVC support is still a experimental feature, we don't want
597 // to report support for it arbitrarily.
598 bool supported = trackSupport.contains(TrackSupport::EncodeVideo);
599 if (aCodec == CodecType::H265) {
600 if (!StaticPrefs::media_hevc_enabled()) {
601 return EncodeSupportSet{};
602 }
603#if defined(XP_WIN)
604 supported = aLocation == RemoteMediaIn::GpuProcess;
605#endif
606 }
607 return supported ? EncodeSupportSet{EncodeSupport::SoftwareEncode}
608 : EncodeSupportSet{};
609 }
610 if (IsAudio(aCodec)) {
611 return trackSupport.contains(TrackSupport::EncodeAudio)
612 ? EncodeSupportSet{EncodeSupport::SoftwareEncode}
613 : EncodeSupportSet{};
614 }
615 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"
, 615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Not audio and video?!" ")"); do {
MOZ_CrashSequence(__null, 615); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
616 return EncodeSupportSet{};
617 }
618
619 // We can ignore the rest of EncoderConfig for now as creation of the encoder
620 // will actually fail later and fallback PEMs will be tested on later.
621 return PEMFactory::SupportsCodec(aCodec, *supported, aLocation);
622}
623
624/* static */ RefPtr<PlatformEncoderModule::CreateEncoderPromise>
625RemoteMediaManagerChild::InitializeEncoder(
626 RefPtr<RemoteMediaDataEncoder>&& aEncoder, const EncoderConfig& aConfig) {
627 RemoteMediaIn location = aEncoder->GetLocation();
628
629 TrackSupport required;
630 if (aConfig.IsAudio()) {
1
Taking true branch
631 required = TrackSupport::EncodeAudio;
632 } else if (aConfig.IsVideo()) {
633 required = TrackSupport::EncodeVideo;
634 } else {
635 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
636 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
637 nsPrintfCString("%s doesn't support encoding",
638 RemoteMediaInToStr(location))
639 .get()),
640 __func__);
641 }
642
643 if (!GetTrackSupport(location).contains(required)) {
2
Assuming the condition is false
3
Taking false branch
644 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
645 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
646 nsPrintfCString("%s doesn't support encoding",
647 RemoteMediaInToStr(location))
648 .get()),
649 __func__);
650 }
651
652 auto managerThread = aEncoder->GetManagerThread();
653 if (!managerThread) {
4
Assuming 'managerThread' is non-null
5
Taking false branch
654 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
655 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED, "Thread shutdown"_ns),
656 __func__);
657 }
658
659 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"
, 659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "location != RemoteMediaIn::Unspecified"
")"); do { MOZ_CrashSequence(__null, 659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6
Taking false branch
7
Loop condition is false. Exiting loop
660
661 RefPtr<GenericNonExclusivePromise> p;
662 if (location
7.1
'location' is equal to UtilityProcess_Generic
7.1
'location' is equal to UtilityProcess_Generic
7.1
'location' is equal to UtilityProcess_Generic
7.1
'location' is equal to UtilityProcess_Generic
== RemoteMediaIn::UtilityProcess_Generic ||
663 location == RemoteMediaIn::UtilityProcess_AppleMedia ||
664 location == RemoteMediaIn::UtilityProcess_WMF) {
665 p = LaunchUtilityProcessIfNeeded(location);
8
Calling 'RemoteMediaManagerChild::LaunchUtilityProcessIfNeeded'
666 } else if (location == RemoteMediaIn::GpuProcess) {
667 p = GenericNonExclusivePromise::CreateAndResolve(true, __func__);
668 } else if (location == RemoteMediaIn::RddProcess) {
669 p = LaunchRDDProcessIfNeeded();
670 } else {
671 p = GenericNonExclusivePromise::CreateAndReject(
672 NS_ERROR_DOM_MEDIA_DENIED_IN_NON_UTILITY, __func__);
673 }
674 LOG("Creating {} encoder type {} in {}",
675 aConfig.IsAudio() ? "audio" : "video", static_cast<int>(aConfig.mCodec),
676 RemoteMediaInToStr(location));
677
678 return p->Then(
679 managerThread, __func__,
680 [encoder = std::move(aEncoder), aConfig](bool) {
681 auto* manager = GetSingleton(encoder->GetLocation());
682 if (!manager) {
683 LOG("Create encoder in {} failed, shutdown",
684 RemoteMediaInToStr(encoder->GetLocation()));
685 // We got shutdown.
686 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
687 MediaResult(NS_ERROR_DOM_MEDIA_CANCELED,
688 "Remote manager not available"),
689 __func__);
690 }
691 if (!manager->SendPRemoteEncoderConstructor(encoder->GetChild(),
692 aConfig)) {
693 LOG("Create encoder in {} failed, send failed",
694 RemoteMediaInToStr(encoder->GetLocation()));
695 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
696 MediaResult(NS_ERROR_NOT_AVAILABLE,
697 "Failed to construct encoder actor"),
698 __func__);
699 }
700 return encoder->Construct();
701 },
702 [location](nsresult aResult) {
703 LOG("Create encoder in {} failed, cannot start process",
704 RemoteMediaInToStr(location));
705 return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
706 MediaResult(aResult, "Couldn't start encode process"), __func__);
707 });
708}
709
710/* static */
711RefPtr<GenericNonExclusivePromise>
712RemoteMediaManagerChild::LaunchRDDProcessIfNeeded() {
713 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"
, 714); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Only supported from a content process." ")"); do { MOZ_CrashSequence
(__null, 714); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
714 "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"
, 714); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Only supported from a content process." ")"); do { MOZ_CrashSequence
(__null, 714); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
715
716 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
717 if (!managerThread) {
718 // We got shutdown.
719 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
720 __func__);
721 }
722
723 StaticMutexAutoLock lock(sLaunchMutex);
724 auto& rddLaunchPromise = sLaunchPromises[RemoteMediaIn::RddProcess];
725 if (rddLaunchPromise) {
726 return rddLaunchPromise;
727 }
728
729 // We have a couple possible states here. We are in a content process
730 // and:
731 // 1) the RDD process has never been launched. RDD should be launched
732 // and the IPC connections setup.
733 // 2) the RDD process has been launched, but this particular content
734 // process has not setup (or has lost) its IPC connection.
735 // In the code below, we assume we need to launch the RDD process and
736 // setup the IPC connections. However, if the manager thread for
737 // RemoteMediaManagerChild is available we do a quick check to see
738 // if we can send (meaning the IPC channel is open). If we can send,
739 // then no work is necessary. If we can't send, then we call
740 // LaunchRDDProcess which will launch RDD if necessary, and setup the
741 // IPC connections between *this* content process and the RDD process.
742
743 RefPtr<GenericNonExclusivePromise> p = InvokeAsync(
744 managerThread, __func__, []() -> RefPtr<GenericNonExclusivePromise> {
745 auto* rps = GetSingleton(RemoteMediaIn::RddProcess);
746 if (rps && rps->CanSend()) {
747 return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
748 }
749 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
750 ipc::PBackgroundChild* bgActor =
751 ipc::BackgroundChild::GetForCurrentThread();
752 if (!managerThread || NS_WARN_IF(!bgActor)NS_warn_if_impl(!bgActor, "!bgActor", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 752)
) {
753 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
754 __func__);
755 }
756
757 return bgActor->SendEnsureRDDProcessAndCreateBridge()->Then(
758 managerThread, __func__,
759 [](ipc::PBackgroundChild::EnsureRDDProcessAndCreateBridgePromise::
760 ResolveOrRejectValue&& aResult) {
761 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
762 if (!managerThread || aResult.IsReject()) {
763 // The parent process died or we got shutdown
764 return GenericNonExclusivePromise::CreateAndReject(
765 NS_ERROR_FAILURE, __func__);
766 }
767 nsresult rv = std::get<0>(aResult.ResolveValue());
768 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
769 return GenericNonExclusivePromise::CreateAndReject(rv,
770 __func__);
771 }
772 OpenRemoteMediaManagerChildForProcess(
773 std::get<1>(std::move(aResult.ResolveValue())),
774 RemoteMediaIn::RddProcess);
775 return GenericNonExclusivePromise::CreateAndResolve(true,
776 __func__);
777 });
778 });
779
780 // This should not be dispatched to a threadpool thread, so use managerThread
781 p = p->Then(
782 managerThread, __func__,
783 [](const GenericNonExclusivePromise::ResolveOrRejectValue& aResult) {
784 StaticMutexAutoLock lock(sLaunchMutex);
785 sLaunchPromises[RemoteMediaIn::RddProcess] = nullptr;
786 return GenericNonExclusivePromise::CreateAndResolveOrReject(aResult,
787 __func__);
788 });
789
790 rddLaunchPromise = p;
791 return rddLaunchPromise;
792}
793
794/* static */
795RefPtr<GenericNonExclusivePromise>
796RemoteMediaManagerChild::LaunchUtilityProcessIfNeeded(RemoteMediaIn aLocation) {
797 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"
, 798); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Only supported from a content process." ")"); do { MOZ_CrashSequence
(__null, 798); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
9
Assuming the condition is false
10
Taking false branch
11
Loop condition is false. Exiting loop
798 "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"
, 798); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "XRE_IsContentProcess()"
") (" "Only supported from a content process." ")"); do { MOZ_CrashSequence
(__null, 798); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
799
800 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
801 if (!managerThread) {
802 // We got shutdown.
803 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
804 __func__);
805 }
806
807 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"
, 810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 810); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12
Taking false branch
13
Taking false branch
14
Loop condition is false. Exiting loop
808 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"
, 810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 810); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
809 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"
, 810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 810); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
810 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"
, 810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation == RemoteMediaIn::UtilityProcess_Generic || aLocation == RemoteMediaIn::UtilityProcess_AppleMedia || aLocation == RemoteMediaIn::UtilityProcess_WMF || aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM"
")"); do { MOZ_CrashSequence(__null, 810); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
811 StaticMutexAutoLock lock(sLaunchMutex);
812 auto& utilityLaunchPromise = sLaunchPromises[aLocation];
813
814 if (utilityLaunchPromise) {
15
Assuming the condition is false
16
Taking false branch
815 return utilityLaunchPromise;
816 }
817
818 // We have a couple possible states here. We are in a content process
819 // and:
820 // 1) the Utility process has never been launched. Utility should be launched
821 // and the IPC connections setup.
822 // 2) the Utility process has been launched, but this particular content
823 // process has not setup (or has lost) its IPC connection.
824 // In the code below, we assume we need to launch the Utility process and
825 // setup the IPC connections. However, if the manager thread for
826 // RemoteMediaManagerChild is available we do a quick check to see
827 // if we can send (meaning the IPC channel is open). If we can send,
828 // then no work is necessary. If we can't send, then we call
829 // LaunchUtilityProcess which will launch Utility if necessary, and setup the
830 // IPC connections between *this* content process and the Utility process.
831
832 RefPtr<GenericNonExclusivePromise> p = InvokeAsync(
833 managerThread, __func__,
834 [aLocation]() -> RefPtr<GenericNonExclusivePromise> {
835 auto* rps = GetSingleton(aLocation);
836 if (rps && rps->CanSend()) {
837 return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
838 }
839 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
840 ipc::PBackgroundChild* bgActor =
841 ipc::BackgroundChild::GetForCurrentThread();
842 if (!managerThread || NS_WARN_IF(!bgActor)NS_warn_if_impl(!bgActor, "!bgActor", "/root/firefox-clang/dom/media/ipc/RemoteMediaManagerChild.cpp"
, 842)
) {
843 return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
844 __func__);
845 }
846
847 return bgActor->SendEnsureUtilityProcessAndCreateBridge(aLocation)
848 ->Then(managerThread, __func__,
849 [aLocation](ipc::PBackgroundChild::
850 EnsureUtilityProcessAndCreateBridgePromise::
851 ResolveOrRejectValue&& aResult)
852 -> RefPtr<GenericNonExclusivePromise> {
853 nsCOMPtr<nsISerialEventTarget> managerThread =
854 GetManagerThread();
855 if (!managerThread || aResult.IsReject()) {
856 // The parent process died or we got shutdown
857 return GenericNonExclusivePromise::CreateAndReject(
858 NS_ERROR_FAILURE, __func__);
859 }
860 nsresult rv = std::get<0>(aResult.ResolveValue());
861 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
862 return GenericNonExclusivePromise::CreateAndReject(
863 rv, __func__);
864 }
865 OpenRemoteMediaManagerChildForProcess(
866 std::get<1>(std::move(aResult.ResolveValue())),
867 aLocation);
868 return GenericNonExclusivePromise::CreateAndResolve(
869 true, __func__);
870 });
871 });
872
873 // Let's make sure this promise is also run on the managerThread to avoid
874 // situations where it would be run on a threadpool thread.
875 // During bug 1794988 this was happening when enabling Utility for audio on
876 // Android when running the sequence of tests
877 // dom/media/test/test_access_control.html
878 // dom/media/test/test_arraybuffer.html
879 //
880 // We would have a launched utility process but the promises would not have
881 // been cleared, so any subsequent tentative to perform audio decoding would
882 // think the process is not yet ran and it would try to wait on the pending
883 // promises.
884 p = p->Then(
17
Calling copy assignment operator for 'RefPtr<mozilla::MozPromise<bool, nsresult, false>>'
39
Returning; memory was released
885 managerThread, __func__,
886 [aLocation](
887 const GenericNonExclusivePromise::ResolveOrRejectValue& aResult) {
888 StaticMutexAutoLock lock(sLaunchMutex);
889 sLaunchPromises[aLocation] = nullptr;
890 return GenericNonExclusivePromise::CreateAndResolveOrReject(aResult,
891 __func__);
892 });
40
Calling '~ThenCommand'
893 utilityLaunchPromise = p;
894 return utilityLaunchPromise;
895}
896
897/* static */
898TrackSupportSet RemoteMediaManagerChild::GetTrackSupport(
899 RemoteMediaIn aLocation) {
900 TrackSupportSet s{TrackSupport::None};
901 switch (aLocation) {
902 case RemoteMediaIn::GpuProcess:
903 s = TrackSupport::DecodeVideo;
904 if (StaticPrefs::media_use_remote_encoder_video_platform()) {
905 s += TrackSupport::EncodeVideo;
906 }
907 break;
908 case RemoteMediaIn::RddProcess:
909 s = TrackSupport::DecodeVideo;
910 if (StaticPrefs::media_use_remote_encoder_video_software() ||
911 StaticPrefs::media_use_remote_encoder_video_platform()) {
912 s += TrackSupport::EncodeVideo;
913 }
914#ifndef ANDROID
915 // Only use RDD for audio coding if we don't have the utility process. If
916 // we have a CDM (which we can't determine here) on Android, then we want
917 // to perform both the video and audio decoding in the RDD so that they
918 // can share the CDM instance.
919 if (!StaticPrefs::media_utility_process_enabled())
920#endif
921 {
922 s += TrackSupport::DecodeAudio;
923 if (StaticPrefs::media_use_remote_encoder_audio_software()) {
924 s += TrackSupport::EncodeAudio;
925 }
926 }
927 break;
928 case RemoteMediaIn::UtilityProcess_Generic:
929 case RemoteMediaIn::UtilityProcess_AppleMedia:
930 case RemoteMediaIn::UtilityProcess_WMF:
931 if (StaticPrefs::media_utility_process_enabled()) {
932 s = TrackSupport::DecodeAudio;
933 if (StaticPrefs::media_use_remote_encoder_audio_software()) {
934 s += TrackSupport::EncodeAudio;
935 }
936 }
937 break;
938 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM:
939#ifdef MOZ_WMF_MEDIA_ENGINE
940 // When we enable the media engine, it would need both tracks to
941 // synchronize the a/v playback.
942 if (StaticPrefs::media_wmf_media_engine_enabled()) {
943 s = TrackSupportSet{TrackSupport::DecodeAudio,
944 TrackSupport::DecodeVideo};
945 }
946#endif
947 break;
948 default:
949 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"
, 949); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Undefined location!" ")"); do { MOZ_CrashSequence
(__null, 949); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
950 break;
951 }
952 return s;
953}
954
955RemoteMediaManagerChild::RemoteMediaManagerChild(RemoteMediaIn aLocation)
956 : mLocation(aLocation) {
957 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"
, 962); 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, 962); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
958 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"
, 962); 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, 962); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
959 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"
, 962); 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, 962); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
960 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"
, 962); 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, 962); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
961 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"
, 962); 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, 962); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
962 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"
, 962); 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, 962); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
963}
964
965/* static */
966void RemoteMediaManagerChild::OpenRemoteMediaManagerChildForProcess(
967 Endpoint<PRemoteMediaManagerChild>&& aEndpoint, RemoteMediaIn aLocation) {
968 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
969 if (!managerThread) {
970 // We've been shutdown, bail.
971 return;
972 }
973 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"
, 973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "managerThread->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 973); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
974
975 // For GPU process, make sure we always dispatch everything in sRecreateTasks,
976 // even if we fail since this is as close to being recreated as we will ever
977 // be.
978 auto runRecreateTasksIfNeeded = MakeScopeExit([aLocation]() {
979 if (aLocation == RemoteMediaIn::GpuProcess) {
980 for (Runnable* task : *sRecreateTasks) {
981 task->Run();
982 }
983 sRecreateTasks->Clear();
984 }
985 });
986
987 // Only create RemoteMediaManagerChild, bind new endpoint and init
988 // ipdl if:
989 // 1) haven't init'd sRemoteMediaManagerChildForProcesses[aLocation]
990 // or
991 // 2) if ActorDestroy was called meaning the other end of the ipc channel was
992 // torn down
993 // But for GPU process, we always recreate a new manager child.
994 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"
, 994); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLocation != RemoteMediaIn::SENTINEL"
")"); do { MOZ_CrashSequence(__null, 994); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
995 auto& remoteDecoderManagerChild =
996 sRemoteMediaManagerChildForProcesses[aLocation];
997 if (aLocation != RemoteMediaIn::GpuProcess && remoteDecoderManagerChild &&
998 remoteDecoderManagerChild->CanSend()) {
999 return;
1000 }
1001 remoteDecoderManagerChild = nullptr;
1002 if (aEndpoint.IsValid()) {
1003 RefPtr<RemoteMediaManagerChild> manager =
1004 new RemoteMediaManagerChild(aLocation);
1005 if (aEndpoint.Bind(manager)) {
1006 remoteDecoderManagerChild = manager;
1007 }
1008 }
1009}
1010
1011bool RemoteMediaManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem) {
1012 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1013 if (!managerThread) {
1014 return false;
1015 }
1016 if (!managerThread->IsOnCurrentThread()) {
1017 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"
, 1023); 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, 1023); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1018 "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"
, 1023); 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, 1023); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1019 [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"
, 1023); 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, 1023); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1020 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"
, 1023); 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, 1023); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1021 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"
, 1023); 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, 1023); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1022 }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"
, 1023); 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, 1023); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1023 })))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"
, 1023); 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, 1023); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1024 return true;
1025 }
1026 return PRemoteMediaManagerChild::DeallocShmem(aShmem);
1027}
1028
1029static already_AddRefed<gfx::DataSourceSurface> GetSurfaceForDescriptor(
1030 const SurfaceDescriptor& aDescriptor) {
1031 const auto& sdb = aDescriptor.get_SurfaceDescriptorBuffer();
1032 const auto& shmem = sdb.data().get_Shmem();
1033 const auto& rgb = sdb.desc().get_RGBDescriptor();
1034 const auto stride = ImageDataSerializer::GetRGBStride(rgb);
1035 if (stride.isNothing()) {
1036 LOGE("Invalid stride for buffer");
1037 return nullptr;
1038 }
1039 const auto requiredSize =
1040 ImageDataSerializer::ComputeRGBBufferSize(rgb.size(), rgb.format());
1041 if (requiredSize.isNothing() || shmem.Size<uint8_t>() < *requiredSize) {
1042 LOGE("Shmem too small for required buffer size");
1043 return nullptr;
1044 }
1045
1046 return gfx::Factory::CreateWrappingDataSourceSurface(
1047 shmem.get<uint8_t>(), *stride, rgb.size(), rgb.format());
1048}
1049
1050static void DestroySurfaceDescriptor(ipc::IShmemAllocator* aAllocator,
1051 SurfaceDescriptor* aSurface) {
1052 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"
, 1052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSurface" ")"
); do { MOZ_CrashSequence(__null, 1052); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1053 const SurfaceDescriptorBuffer& desc = aSurface->get_SurfaceDescriptorBuffer();
1054 aAllocator->DeallocShmem(desc.data().get_Shmem());
1055 *aSurface = SurfaceDescriptor();
1056}
1057
1058struct SurfaceDescriptorUserData {
1059 SurfaceDescriptorUserData(RemoteMediaManagerChild* aAllocator,
1060 SurfaceDescriptor& aSD)
1061 : mAllocator(aAllocator), mSD(aSD) {}
1062 ~SurfaceDescriptorUserData() { DestroySurfaceDescriptor(mAllocator, &mSD); }
1063
1064 RefPtr<RemoteMediaManagerChild> mAllocator;
1065 SurfaceDescriptor mSD;
1066};
1067
1068void DeleteSurfaceDescriptorUserData(void* aClosure) {
1069 SurfaceDescriptorUserData* sd =
1070 reinterpret_cast<SurfaceDescriptorUserData*>(aClosure);
1071 delete sd;
1072}
1073
1074already_AddRefed<SourceSurface> RemoteMediaManagerChild::Readback(
1075 const SurfaceDescriptorGPUVideo& aSD) {
1076 // We can't use NS_DispatchAndSpinEventLoopUntilComplete here since that will
1077 // spin the event loop while it waits. This function can be called from JS and
1078 // we don't want that to happen.
1079 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1080 if (!managerThread) {
1081 return nullptr;
1082 }
1083
1084 SurfaceDescriptor sd;
1085 RefPtr<Runnable> task =
1086 NS_NewRunnableFunction("RemoteMediaManagerChild::Readback", [&]() {
1087 if (CanSend()) {
1088 SendReadback(aSD, &sd);
1089 }
1090 });
1091 SyncRunnable::DispatchToThread(managerThread, task);
1092
1093 if (sd.type() != SurfaceDescriptor::TSurfaceDescriptorBuffer) {
1094 LOGE("Unexpected SurfaceDescriptor type in Readback");
1095 return nullptr;
1096 }
1097 auto& sdb = sd.get_SurfaceDescriptorBuffer();
1098 if (sdb.data().type() != MemoryOrShmem::TShmem) {
1099 LOGE("Unexpected SurfaceDescriptorBuffer data type in Readback");
1100 return nullptr;
1101 }
1102
1103 RefPtr<DataSourceSurface> source = GetSurfaceForDescriptor(sd);
1104 if (!source) {
1105 DestroySurfaceDescriptor(this, &sd);
1106 LOGE("Failed to map SurfaceDescriptor in Readback");
1107 return nullptr;
1108 }
1109
1110 static UserDataKey sSurfaceDescriptor;
1111 source->AddUserData(&sSurfaceDescriptor,
1112 new SurfaceDescriptorUserData(this, sd),
1113 DeleteSurfaceDescriptorUserData);
1114
1115 return source.forget();
1116}
1117
1118already_AddRefed<Image> RemoteMediaManagerChild::TransferToImage(
1119 const SurfaceDescriptorGPUVideo& aSD, const IntSize& aSize,
1120 const ColorDepth& aColorDepth, YUVColorSpace aYUVColorSpace,
1121 ColorSpace2 aColorPrimaries, TransferFunction aTransferFunction,
1122 ColorRange aColorRange) {
1123 // The Image here creates a TextureData object that takes ownership
1124 // of the SurfaceDescriptor, and is responsible for making sure that
1125 // it gets deallocated.
1126 SurfaceDescriptorGPUVideo sd(aSD);
1127 sd.get_SurfaceDescriptorRemoteDecoder().source() =
1128 Some(GetVideoBridgeSourceFromRemoteMediaIn(mLocation));
1129 return MakeAndAddRef<GPUVideoImage>(this, sd, aSize, aColorDepth,
1130 aYUVColorSpace, aColorPrimaries,
1131 aTransferFunction, aColorRange);
1132}
1133
1134void RemoteMediaManagerChild::DeallocateSurfaceDescriptor(
1135 const SurfaceDescriptorGPUVideo& aSD) {
1136 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1137 if (!managerThread) {
1138 return;
1139 }
1140 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"
, 1146); 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, 1146); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1141 "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"
, 1146); 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, 1146); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1142 [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"
, 1146); 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, 1146); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1143 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"
, 1146); 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, 1146); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1144 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"
, 1146); 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, 1146); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1145 }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"
, 1146); 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, 1146); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1146 })))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"
, 1146); 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, 1146); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1147}
1148
1149void RemoteMediaManagerChild::OnSetCurrent(
1150 const SurfaceDescriptorGPUVideo& aSD) {
1151 nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
1152 if (!managerThread) {
1153 return;
1154 }
1155 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"
, 1161); 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, 1161); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1156 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"
, 1161); 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, 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::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"
, 1161); 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, 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::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"
, 1161); 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, 1161); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1159 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"
, 1161); 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, 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::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"
, 1161); 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, 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::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"
, 1161); 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, 1161); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1162}
1163
1164/* static */ void RemoteMediaManagerChild::HandleRejectionError(
1165 const RemoteMediaManagerChild* aDyingManager, RemoteMediaIn aLocation,
1166 const ipc::ResponseRejectReason& aReason,
1167 std::function<void(const MediaResult&)>&& aCallback) {
1168 // If the channel goes down and CanSend() returns false, the IPDL promise will
1169 // be rejected with SendError rather than ActorDestroyed. Both means the same
1170 // thing and we can consider that the parent has crashed. The child can no
1171 // longer be used.
1172
1173 if (aLocation == RemoteMediaIn::GpuProcess) {
1174 // The GPU process will get automatically restarted by the parent process.
1175 // Once it has been restarted the ContentChild will receive the message and
1176 // will call GetManager()->InitForGPUProcess.
1177 // We defer reporting an error until we've recreated the RemoteDecoder
1178 // manager so that it'll be safe for MediaFormatReader to recreate decoders
1179 RunWhenGPUProcessRecreated(
1180 aDyingManager,
1181 NS_NewRunnableFunction(
1182 "RemoteMediaManagerChild::HandleRejectionError",
1183 [callback = std::move(aCallback)]() {
1184 MediaResult error(
1185 NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_RDD_OR_GPU_ERR, __func__);
1186 callback(error);
1187 }));
1188 return;
1189 }
1190
1191 nsresult err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_UTILITY_ERR;
1192 if (aLocation == RemoteMediaIn::RddProcess) {
1193 err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_RDD_OR_GPU_ERR;
1194 } else if (aLocation == RemoteMediaIn::UtilityProcess_MFMediaEngineCDM) {
1195 err = NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_MF_CDM_ERR;
1196 }
1197 // The RDD/utility process is restarted on demand and asynchronously, we can
1198 // immediately inform the caller that a new en/decoder is needed. The process
1199 // will then be restarted during the new en/decoder creation by
1200 aCallback(MediaResult(err, __func__));
1201}
1202
1203void RemoteMediaManagerChild::HandleFatalError(const char* aMsg) {
1204 dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherChildID());
1205}
1206
1207void RemoteMediaManagerChild::SetSupported(
1208 RemoteMediaIn aLocation, const media::MediaCodecsSupported& aSupported) {
1209 switch (aLocation) {
1210 case RemoteMediaIn::GpuProcess:
1211 case RemoteMediaIn::RddProcess:
1212 case RemoteMediaIn::UtilityProcess_AppleMedia:
1213 case RemoteMediaIn::UtilityProcess_Generic:
1214 case RemoteMediaIn::UtilityProcess_WMF:
1215 case RemoteMediaIn::UtilityProcess_MFMediaEngineCDM: {
1216 StaticMutexAutoLock lock(sProcessSupportedMutex);
1217 sProcessSupported[aLocation] = Some(aSupported);
1218 break;
1219 }
1220 default:
1221 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"
, 1221); AnnotateMozCrashReason("MOZ_CRASH(" "Not to be used for any other process"
")"); do { MOZ_CrashSequence(__null, 1221); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1222 }
1223}
1224
1225#undef LOG
1226#undef LOGE
1227
1228} // 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(); }
25
Calling 'MozPromiseRefcountable::Release'
34
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) {
19
Assuming 'aRawPtr' is null
20
Taking false branch
59 ConstRemovingRefPtrTraits<T>::AddRef(aRawPtr);
60 }
61 assign_assuming_AddRef(aRawPtr);
21
Calling 'RefPtr::assign_assuming_AddRef'
37
Returning; memory was released
62 }
63
64 void assign_assuming_AddRef(T* aNewPtr) {
65 T* oldPtr = mRawPtr;
66 mRawPtr = aNewPtr;
67 if (oldPtr
21.1
'oldPtr' is non-null
21.1
'oldPtr' is non-null
21.1
'oldPtr' is non-null
21.1
'oldPtr' is non-null
) {
22
Taking true branch
68 ConstRemovingRefPtrTraits<T>::Release(oldPtr);
23
Calling 'ConstRemovingRefPtrTraits::Release'
36
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
42.1
Field 'mRawPtr' is non-null
42.1
Field 'mRawPtr' is non-null
42.1
Field 'mRawPtr' is non-null
42.1
Field 'mRawPtr' is non-null
) {
43
Taking true branch
80 ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
44
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);
18
Calling 'RefPtr::assign_with_AddRef'
38
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); }
24
Calling 'RefPtrTraits::Release'
35
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:
26
Assuming the condition is true
27
Taking false branch
28
Loop condition is false. Exiting loop
29
Assuming 'count' is equal to 0
30
Taking true branch
31
Calling 'operator delete'
33
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 T>
163class MozPromiseRequestHolder;
164template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
165class MozPromise : public MozPromiseBase {
166 static const uint32_t sMagic = 0xcecace11;
167
168 // Return a |T&&| to enable move when IsExclusive is true or
169 // a |const T&| to enforce copy otherwise.
170 template <typename T,
171 typename R = std::conditional_t<IsExclusive, T&&, const T&>>
172 static R MaybeMove(T& aX) {
173 return static_cast<R>(aX);
174 }
175
176 public:
177 using ResolveValueType = ResolveValueT;
178 using RejectValueType = RejectValueT;
179 class ResolveOrRejectValue {
180 public:
181 template <typename ResolveValueType_>
182 void SetResolve(ResolveValueType_&& aResolveValue) {
183 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"
, 183); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNothing()"
")"); do { MOZ_CrashSequence(__null, 183); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
184 mValue = Storage(VariantIndex<ResolveIndex>{},
185 std::forward<ResolveValueType_>(aResolveValue));
186 }
187
188 template <typename RejectValueType_>
189 void SetReject(RejectValueType_&& aRejectValue) {
190 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"
, 190); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNothing()"
")"); do { MOZ_CrashSequence(__null, 190); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
191 mValue = Storage(VariantIndex<RejectIndex>{},
192 std::forward<RejectValueType_>(aRejectValue));
193 }
194
195 template <typename ResolveValueType_>
196 static ResolveOrRejectValue MakeResolve(ResolveValueType_&& aResolveValue) {
197 ResolveOrRejectValue val;
198 val.SetResolve(std::forward<ResolveValueType_>(aResolveValue));
199 return val;
200 }
201
202 template <typename RejectValueType_>
203 static ResolveOrRejectValue MakeReject(RejectValueType_&& aRejectValue) {
204 ResolveOrRejectValue val;
205 val.SetReject(std::forward<RejectValueType_>(aRejectValue));
206 return val;
207 }
208
209 bool IsResolve() const { return mValue.template is<ResolveIndex>(); }
210 bool IsReject() const { return mValue.template is<RejectIndex>(); }
211 bool IsNothing() const { return mValue.template is<NothingIndex>(); }
212
213 const ResolveValueType& ResolveValue() const {
214 return mValue.template as<ResolveIndex>();
215 }
216 ResolveValueType& ResolveValue() {
217 return mValue.template as<ResolveIndex>();
218 }
219 const RejectValueType& RejectValue() const {
220 return mValue.template as<RejectIndex>();
221 }
222 RejectValueType& RejectValue() { return mValue.template as<RejectIndex>(); }
223
224 private:
225 enum { NothingIndex, ResolveIndex, RejectIndex };
226 using Storage = Variant<Nothing, ResolveValueType, RejectValueType>;
227 Storage mValue = Storage(VariantIndex<NothingIndex>{});
228 };
229
230 protected:
231 // MozPromise is the public type, and never constructed directly. Construct
232 // a MozPromise::Private, defined below.
233 MozPromise(StaticString aCreationSite, bool aIsCompletionPromise)
234 : mCreationSite(aCreationSite),
235 mMutex("MozPromise Mutex"),
236 mHaveRequest(false),
237 mIsCompletionPromise(aIsCompletionPromise)
238#ifdef PROMISE_DEBUG
239 ,
240 mMagic4(&mMutex)
241#endif
242 {
243 PROMISE_LOG("%s creating MozPromise (%p)", mCreationSite.get(), this);
244 }
245
246 public:
247 // MozPromise::Private allows us to separate the public interface (upon which
248 // consumers of the promise may invoke methods like Then()) from the private
249 // interface (upon which the creator of the promise may invoke Resolve() or
250 // Reject()). APIs should create and store a MozPromise::Private (usually
251 // via a MozPromiseHolder), and return a MozPromise to consumers.
252 //
253 // NB: We can include the definition of this class inline once B2G ICS is
254 // gone.
255 class Private;
256
257 template <typename ResolveValueType_>
258 [[nodiscard]] static RefPtr<MozPromise> CreateAndResolve(
259 ResolveValueType_&& aResolveValue, StaticString aResolveSite) {
260 static_assert(std::is_convertible_v<ResolveValueType_, ResolveValueT>,
261 "Resolve() argument must be implicitly convertible to "
262 "MozPromise's ResolveValueT");
263 RefPtr<typename MozPromise::Private> p =
264 new MozPromise::Private(aResolveSite);
265 p->Resolve(std::forward<ResolveValueType_>(aResolveValue), aResolveSite);
266 return p;
267 }
268
269 template <typename RejectValueType_>
270 [[nodiscard]] static RefPtr<MozPromise> CreateAndReject(
271 RejectValueType_&& aRejectValue, StaticString aRejectSite) {
272 static_assert(std::is_convertible_v<RejectValueType_, RejectValueT>,
273 "Reject() argument must be implicitly convertible to "
274 "MozPromise's RejectValueT");
275 RefPtr<typename MozPromise::Private> p =
276 new MozPromise::Private(aRejectSite);
277 p->Reject(std::forward<RejectValueType_>(aRejectValue), aRejectSite);
278 return p;
279 }
280
281 template <typename ResolveOrRejectValueType_>
282 [[nodiscard]] static RefPtr<MozPromise> CreateAndResolveOrReject(
283 ResolveOrRejectValueType_&& aValue, StaticString aSite) {
284 RefPtr<typename MozPromise::Private> p = new MozPromise::Private(aSite);
285 p->ResolveOrReject(std::forward<ResolveOrRejectValueType_>(aValue), aSite);
286 return p;
287 }
288
289 using AllPromiseType = MozPromise<CopyableTArray<ResolveValueType>,
290 RejectValueType, IsExclusive>;
291 using AllSettledPromiseType =
292 MozPromise<CopyableTArray<ResolveOrRejectValue>, bool, IsExclusive>;
293
294 private:
295 class AllPromiseHolder : public MozPromiseRefcountable {
296 public:
297 explicit AllPromiseHolder(size_t aDependentPromises)
298 : mPromise(new typename AllPromiseType::Private(__func__)),
299 mOutstandingPromises(aDependentPromises) {
300 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"
, 300); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDependentPromises > 0"
")"); do { MOZ_CrashSequence(__null, 300); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
301 mResolveValues.SetLength(aDependentPromises);
302 }
303
304 template <typename ResolveValueType_>
305 void Resolve(size_t aIndex, ResolveValueType_&& aResolveValue) {
306 if (!mPromise) {
307 // Already rejected.
308 return;
309 }
310
311 mResolveValues[aIndex].emplace(
312 std::forward<ResolveValueType_>(aResolveValue));
313 if (--mOutstandingPromises == 0) {
314 nsTArray<ResolveValueType> resolveValues;
315 resolveValues.SetCapacity(mResolveValues.Length());
316 for (auto&& resolveValue : mResolveValues) {
317 resolveValues.AppendElement(std::move(resolveValue.ref()));
318 }
319
320 mPromise->Resolve(std::move(resolveValues), __func__);
321 mPromise = nullptr;
322 mResolveValues.Clear();
323 }
324 }
325
326 template <typename RejectValueType_>
327 void Reject(RejectValueType_&& aRejectValue) {
328 if (!mPromise) {
329 // Already rejected.
330 return;
331 }
332
333 mPromise->Reject(std::forward<RejectValueType_>(aRejectValue), __func__);
334 mPromise = nullptr;
335 mResolveValues.Clear();
336 }
337
338 AllPromiseType* Promise() { return mPromise; }
339
340 private:
341 nsTArray<Maybe<ResolveValueType>> mResolveValues;
342 RefPtr<typename AllPromiseType::Private> mPromise;
343 size_t mOutstandingPromises;
344 };
345
346 // Trying to pass ResolveOrRejectValue by value fails static analysis checks,
347 // so we need to use either a const& or an rvalue reference, depending on
348 // whether IsExclusive is true or not.
349 using ResolveOrRejectValueParam =
350 std::conditional_t<IsExclusive, ResolveOrRejectValue&&,
351 const ResolveOrRejectValue&>;
352
353 using ResolveValueTypeParam =
354 std::conditional_t<IsExclusive, ResolveValueType&&,
355 const ResolveValueType&>;
356
357 using RejectValueTypeParam =
358 std::conditional_t<IsExclusive, RejectValueType&&,
359 const RejectValueType&>;
360
361 class AllSettledPromiseHolder : public MozPromiseRefcountable {
362 public:
363 explicit AllSettledPromiseHolder(size_t aDependentPromises)
364 : mPromise(new typename AllSettledPromiseType::Private(__func__)),
365 mOutstandingPromises(aDependentPromises) {
366 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"
, 366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDependentPromises > 0"
")"); do { MOZ_CrashSequence(__null, 366); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
367 mValues.SetLength(aDependentPromises);
368 }
369
370 void Settle(size_t aIndex, ResolveOrRejectValueParam aValue) {
371 if (!mPromise) {
372 // Already rejected.
373 return;
374 }
375
376 mValues[aIndex].emplace(MaybeMove(aValue));
377 if (--mOutstandingPromises == 0) {
378 nsTArray<ResolveOrRejectValue> values;
379 values.SetCapacity(mValues.Length());
380 for (auto&& value : mValues) {
381 values.AppendElement(std::move(value.ref()));
382 }
383
384 mPromise->Resolve(std::move(values), __func__);
385 mPromise = nullptr;
386 mValues.Clear();
387 }
388 }
389
390 AllSettledPromiseType* Promise() { return mPromise; }
391
392 private:
393 nsTArray<Maybe<ResolveOrRejectValue>> mValues;
394 RefPtr<typename AllSettledPromiseType::Private> mPromise;
395 size_t mOutstandingPromises;
396 };
397
398 public:
399 [[nodiscard]] static RefPtr<AllPromiseType> All(
400 nsISerialEventTarget* aProcessingTarget,
401 nsTArray<RefPtr<MozPromise>>& aPromises) {
402 if (aPromises.Length() == 0) {
403 return AllPromiseType::CreateAndResolve(
404 CopyableTArray<ResolveValueType>(), __func__);
405 }
406
407 RefPtr holder = MakeRefPtr<AllPromiseHolder>(aPromises.Length());
408 RefPtr<AllPromiseType> promise = holder->Promise();
409 for (size_t i = 0; i < aPromises.Length(); ++i) {
410 aPromises[i]->Then(
411 aProcessingTarget, __func__,
412 [holder, i](ResolveValueTypeParam aResolveValue) -> void {
413 holder->Resolve(i, MaybeMove(aResolveValue));
414 },
415 [holder](RejectValueTypeParam aRejectValue) -> void {
416 holder->Reject(MaybeMove(aRejectValue));
417 });
418 }
419 return promise;
420 }
421
422 [[nodiscard]] static RefPtr<AllSettledPromiseType> AllSettled(
423 nsISerialEventTarget* aProcessingTarget,
424 nsTArray<RefPtr<MozPromise>>& aPromises) {
425 if (aPromises.Length() == 0) {
426 return AllSettledPromiseType::CreateAndResolve(
427 CopyableTArray<ResolveOrRejectValue>(), __func__);
428 }
429
430 RefPtr holder = MakeRefPtr<AllSettledPromiseHolder>(aPromises.Length());
431 RefPtr<AllSettledPromiseType> promise = holder->Promise();
432 for (size_t i = 0; i < aPromises.Length(); ++i) {
433 aPromises[i]->Then(aProcessingTarget, __func__,
434 [holder, i](ResolveOrRejectValueParam aValue) -> void {
435 holder->Settle(i, MaybeMove(aValue));
436 });
437 }
438 return promise;
439 }
440
441 class Request : public MozPromiseRefcountable {
442 public:
443 virtual void Disconnect() = 0;
444
445 protected:
446 Request() : mComplete(false), mDisconnected(false) {}
447 virtual ~Request() = default;
448
449 bool mComplete;
450 bool mDisconnected;
451 };
452
453 protected:
454 /*
455 * A ThenValue tracks a single consumer waiting on the promise. When a
456 * consumer invokes promise->Then(...), a ThenValue is created. Once the
457 * Promise is resolved or rejected, a {Resolve,Reject}Runnable is dispatched,
458 * which invokes the resolve/reject method and then deletes the ThenValue.
459 */
460 class ThenValueBase : public Request {
461 friend class MozPromise;
462 static const uint32_t sMagic = 0xfadece11;
463
464 public:
465 class ResolveOrRejectRunnable final
466 : public PrioritizableCancelableRunnable {
467 public:
468 ResolveOrRejectRunnable(ThenValueBase* aThenValue, MozPromise* aPromise)
469 : PrioritizableCancelableRunnable(
470 aPromise->mPriority,
471 "MozPromise::ThenValueBase::ResolveOrRejectRunnable"),
472 mThenValue(aThenValue),
473 mPromise(aPromise) {
474 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"
, 474); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mPromise->IsPending()"
")"); do { MOZ_CrashSequence(__null, 474); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
475 }
476
477#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
478 // nsINamed
479 NS_IMETHODvirtual nsresult GetName(nsACString& aName) override {
480 nsresult rv = PrioritizableCancelableRunnable::GetName(aName);
481 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
482 return rv;
483 }
484
485 if (mPromise) {
486 aName.Append(" ");
487 aName.Append(mPromise->mCreationSite);
488 };
489
490 return NS_OK;
491 }
492#endif
493
494 ~ResolveOrRejectRunnable() {
495 if (mThenValue) {
496 mThenValue->AssertIsDead();
497 }
498 }
499
500 NS_IMETHODvirtual nsresult Run() override {
501 PROMISE_LOG("ResolveOrRejectRunnable::Run() [this=%p]", this);
502 mThenValue->DoResolveOrReject(mPromise->Value());
503 mThenValue = nullptr;
504 mPromise = nullptr;
505 return NS_OK;
506 }
507
508 nsresult Cancel() override { return Run(); }
509
510 private:
511 RefPtr<ThenValueBase> mThenValue;
512 RefPtr<MozPromise> mPromise;
513 };
514
515 ThenValueBase(nsISerialEventTarget* aResponseTarget, StaticString aCallSite)
516 : mResponseTarget(aResponseTarget), mCallSite(aCallSite) {
517 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"
, 517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aResponseTarget"
")"); do { MOZ_CrashSequence(__null, 517); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
518 }
519
520#ifdef PROMISE_DEBUG
521 ~ThenValueBase() {
522 mMagic1 = 0;
523 mMagic2 = 0;
524 }
525#endif
526
527 void AssertIsDead() {
528 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic);
529 // We want to assert that this ThenValues is dead - that is to say, that
530 // there are no consumers waiting for the result. In the case of a normal
531 // ThenValue, we check that it has been disconnected, which is the way
532 // that the consumer signals that it no longer wishes to hear about the
533 // result. If this ThenValue has a completion promise (which is mutually
534 // exclusive with being disconnectable), we recursively assert that every
535 // ThenValue associated with the completion promise is dead.
536 if (MozPromiseBase* p = CompletionPromise()) {
537 p->AssertIsDead();
538 } else {
539#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
540 if (MOZ_UNLIKELY(!Request::mDisconnected)(__builtin_expect(!!(!Request::mDisconnected), 0))) {
541 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"
, 546, 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)
542 "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"
, 546, 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)
543 "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"
, 546, 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 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"
, 546, 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 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"
, 546, 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 : "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"
, 546, 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 }
548#endif
549 }
550 }
551
552 void Dispatch(MozPromise* aPromise) {
553 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic);
554 aPromise->mMutex.AssertCurrentThreadOwns();
555 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"
, 555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPromise->IsPending()"
")"); do { MOZ_CrashSequence(__null, 555); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
556
557 nsCOMPtr<nsIRunnable> r = new ResolveOrRejectRunnable(this, aPromise);
558 PROMISE_LOG(
559 "%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p] "
560 "%s dispatch",
561 aPromise->mValue.IsResolve() ? "Resolving" : "Rejecting",
562 mCallSite.get(), r.get(), aPromise, this,
563 aPromise->mUseSynchronousTaskDispatch ? "synchronous"
564 : aPromise->mUseDirectTaskDispatch ? "directtask"
565 : "normal");
566
567 if (aPromise->mUseSynchronousTaskDispatch &&
568 mResponseTarget->IsOnCurrentThread()) {
569 PROMISE_LOG("ThenValue::Dispatch running task synchronously [this=%p]",
570 this);
571 r->Run();
572 return;
573 }
574
575 if (aPromise->mUseDirectTaskDispatch &&
576 mResponseTarget->IsOnCurrentThread()) {
577 PROMISE_LOG(
578 "ThenValue::Dispatch dispatch task via direct task queue [this=%p]",
579 this);
580 nsCOMPtr<nsIDirectTaskDispatcher> dispatcher =
581 do_QueryInterface(mResponseTarget);
582 if (dispatcher) {
583 SetDispatchRv(dispatcher->DispatchDirectTask(r.forget()));
584 return;
585 }
586 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"
, 590)
587 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"
, 590)
588 "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"
, 590)
589 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"
, 590)
590 .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"
, 590)
;
591 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"
, 594); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")"); do { MOZ_CrashSequence(__null, 594)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
592 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"
, 594); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")"); do { MOZ_CrashSequence(__null, 594)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
593 "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"
, 594); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")"); do { MOZ_CrashSequence(__null, 594)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
594 "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"
, 594); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "mResponseTarget must implement nsIDirectTaskDispatcher for direct "
"task dispatching" ")"); do { MOZ_CrashSequence(__null, 594)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
595 }
596
597 // Promise consumers are allowed to disconnect the Request object and
598 // then shut down the thread or task queue that the promise result would
599 // be dispatched on. So we unfortunately can't assert that promise
600 // dispatch succeeds. :-(
601 // We do record whether or not it succeeds so that if the ThenValueBase is
602 // then destroyed and it was not disconnected, we can include that
603 // information in the assertion message.
604 SetDispatchRv(mResponseTarget->Dispatch(r.forget()));
605 }
606
607 void Disconnect() override {
608 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"
, 608); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mResponseTarget->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 608); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
609 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"
, 609); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!Request::mComplete"
")"); do { MOZ_CrashSequence(__null, 609); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
610 Request::mDisconnected = true;
611
612 // We could support rejecting the completion promise on disconnection, but
613 // then we'd need to have some sort of default reject value. The use cases
614 // of disconnection and completion promise chaining seem pretty
615 // orthogonal, so let's use assert against it.
616 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"
, 616); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!CompletionPromise()"
")"); do { MOZ_CrashSequence(__null, 616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
617 }
618
619 protected:
620 virtual MozPromiseBase* CompletionPromise() const = 0;
621 virtual void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) = 0;
622
623 void DoResolveOrReject(ResolveOrRejectValue& aValue) {
624 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic);
625 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"
, 625); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mResponseTarget->IsOnCurrentThread()"
")"); do { MOZ_CrashSequence(__null, 625); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
626 Request::mComplete = true;
627 if (Request::mDisconnected) {
628 PROMISE_LOG(
629 "ThenValue::DoResolveOrReject disconnected - bailing out [this=%p]",
630 this);
631 return;
632 }
633
634 // Invoke the resolve or reject method.
635 DoResolveOrRejectInternal(aValue);
636 }
637
638 void SetDispatchRv(nsresult aRv) {
639#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
640 mDispatchRv = Some(aRv);
641#endif
642 }
643
644 nsCOMPtr<nsISerialEventTarget>
645 mResponseTarget; // May be released on any thread.
646#ifdef PROMISE_DEBUG
647 uint32_t mMagic1 = sMagic;
648#endif
649 StaticString mCallSite;
650#ifdef PROMISE_DEBUG
651 uint32_t mMagic2 = sMagic;
652#endif
653#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
654 Maybe<nsresult> mDispatchRv;
655#endif
656 };
657
658 /*
659 * Helper to make the resolve/reject value argument "optional".
660 */
661 template <typename ThisType, typename MethodType, typename ValueType>
662 static MethodReturnType<MethodType> InvokeMethod(ThisType* aThisVal,
663 MethodType aMethod,
664 ValueType&& aValue) {
665 if constexpr (TakesAnyArguments<MethodType>) {
666 return (aThisVal->*aMethod)(std::forward<ValueType>(aValue));
667 } else {
668 return (aThisVal->*aMethod)();
669 }
670 }
671
672 template <bool SupportChaining, typename PromiseType, typename ThisType,
673 typename MethodType, typename ValueType>
674 static RefPtr<PromiseType> InvokeCallbackMethod(ThisType* aThisVal,
675 MethodType aMethod,
676 ValueType&& aValue) {
677 if constexpr (SupportChaining) {
678 return InvokeMethod(aThisVal, aMethod, std::forward<ValueType>(aValue));
679 } else {
680 InvokeMethod(aThisVal, aMethod, std::forward<ValueType>(aValue));
681 return nullptr;
682 }
683 }
684
685 template <bool SupportChaining, typename PromiseType>
686 static void MaybeChain(PromiseType* aFrom,
687 RefPtr<typename PromiseType::Private>&& aTo) {
688 if constexpr (SupportChaining) {
689 if (aTo) {
690 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"
, 692); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aFrom"
") (" "Can't do promise chaining for a non-promise-returning method."
")"); do { MOZ_CrashSequence(__null, 692); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
691 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"
, 692); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aFrom"
") (" "Can't do promise chaining for a non-promise-returning method."
")"); do { MOZ_CrashSequence(__null, 692); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
692 "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"
, 692); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aFrom"
") (" "Can't do promise chaining for a non-promise-returning method."
")"); do { MOZ_CrashSequence(__null, 692); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
693 aFrom->ChainTo(aTo.forget(), "<chained completion promise>");
694 }
695 } else {
696 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"
, 697); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aTo"
") (" "A completion promise requires a promise-returning callback."
")"); do { MOZ_CrashSequence(__null, 697); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
697 !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"
, 697); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!aTo"
") (" "A completion promise requires a promise-returning callback."
")"); do { MOZ_CrashSequence(__null, 697); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
698 }
699 }
700
701 template <typename>
702 class ThenCommand;
703
704 template <typename...>
705 class ThenValue;
706
707 template <typename ThisType, typename ResolveMethodType,
708 typename RejectMethodType>
709 class ThenValue<ThisType*, ResolveMethodType, RejectMethodType>
710 : public ThenValueBase {
711 friend class ThenCommand<ThenValue>;
712
713 using R1 = RemoveSmartPointer<MethodReturnType<ResolveMethodType>>;
714 using R2 = RemoveSmartPointer<MethodReturnType<RejectMethodType>>;
715 constexpr static bool SupportChaining =
716 IsMozPromise<R1> && std::is_same_v<R1, R2>;
717
718 // Fall back to MozPromise when promise chaining is not supported to make
719 // code compile.
720 using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
721
722 public:
723 ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
724 ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
725 StaticString aCallSite)
726 : ThenValueBase(aResponseTarget, aCallSite),
727 mThisVal(aThisVal),
728 mResolveMethod(aResolveMethod),
729 mRejectMethod(aRejectMethod) {}
730
731 void Disconnect() override {
732 ThenValueBase::Disconnect();
733
734 // If a Request has been disconnected, we don't guarantee that the
735 // resolve/reject runnable will be dispatched. Null out our refcounted
736 // this-value now so that it's released predictably on the dispatch
737 // thread.
738 mThisVal = nullptr;
739 }
740
741 protected:
742 MozPromiseBase* CompletionPromise() const override {
743 return mCompletionPromise;
744 }
745
746 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
747 RefPtr<PromiseType> result =
748 aValue.IsResolve()
749 ? InvokeCallbackMethod<SupportChaining, PromiseType>(
750 mThisVal.get(), mResolveMethod,
751 MaybeMove(aValue.ResolveValue()))
752 : InvokeCallbackMethod<SupportChaining, PromiseType>(
753 mThisVal.get(), mRejectMethod,
754 MaybeMove(aValue.RejectValue()));
755
756 // Null out mThisVal after invoking the callback so that any references
757 // are released predictably on the dispatch thread. Otherwise, it would be
758 // released on whatever thread last drops its reference to the ThenValue,
759 // which may or may not be ok.
760 mThisVal = nullptr;
761
762 MaybeChain<SupportChaining, PromiseType>(result,
763 std::move(mCompletionPromise));
764 }
765
766 private:
767 RefPtr<ThisType>
768 mThisVal; // Only accessed and refcounted on dispatch thread.
769 ResolveMethodType mResolveMethod;
770 RejectMethodType mRejectMethod;
771 RefPtr<typename PromiseType::Private> mCompletionPromise;
772 };
773
774 template <typename ThisType, typename ResolveRejectMethodType>
775 class ThenValue<ThisType*, ResolveRejectMethodType> : public ThenValueBase {
776 friend class ThenCommand<ThenValue>;
777
778 using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectMethodType>>;
779 constexpr static bool SupportChaining = IsMozPromise<R1>;
780
781 // Fall back to MozPromise when promise chaining is not supported to make
782 // code compile.
783 using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
784
785 public:
786 ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
787 ResolveRejectMethodType aResolveRejectMethod,
788 StaticString aCallSite)
789 : ThenValueBase(aResponseTarget, aCallSite),
790 mThisVal(aThisVal),
791 mResolveRejectMethod(aResolveRejectMethod) {}
792
793 void Disconnect() override {
794 ThenValueBase::Disconnect();
795
796 // If a Request has been disconnected, we don't guarantee that the
797 // resolve/reject runnable will be dispatched. Null out our refcounted
798 // this-value now so that it's released predictably on the dispatch
799 // thread.
800 mThisVal = nullptr;
801 }
802
803 protected:
804 MozPromiseBase* CompletionPromise() const override {
805 return mCompletionPromise;
806 }
807
808 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
809 RefPtr<PromiseType> result =
810 InvokeCallbackMethod<SupportChaining, PromiseType>(
811 mThisVal.get(), mResolveRejectMethod, MaybeMove(aValue));
812
813 // Null out mThisVal after invoking the callback so that any references
814 // are released predictably on the dispatch thread. Otherwise, it would be
815 // released on whatever thread last drops its reference to the ThenValue,
816 // which may or may not be ok.
817 mThisVal = nullptr;
818
819 MaybeChain<SupportChaining, PromiseType>(result,
820 std::move(mCompletionPromise));
821 }
822
823 private:
824 RefPtr<ThisType>
825 mThisVal; // Only accessed and refcounted on dispatch thread.
826 ResolveRejectMethodType mResolveRejectMethod;
827 RefPtr<typename PromiseType::Private> mCompletionPromise;
828 };
829
830 // NB: We could use std::function here instead of a template if it were
831 // supported. :-(
832 template <typename ResolveFunction, typename RejectFunction>
833 class ThenValue<ResolveFunction, RejectFunction> : public ThenValueBase {
834 friend class ThenCommand<ThenValue>;
835
836 using R1 = RemoveSmartPointer<MethodReturnType<ResolveFunction>>;
837 using R2 = RemoveSmartPointer<MethodReturnType<RejectFunction>>;
838 constexpr static bool SupportChaining =
839 IsMozPromise<R1> && std::is_same_v<R1, R2>;
840
841 // Fall back to MozPromise when promise chaining is not supported to make
842 // code compile.
843 using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
844
845 public:
846 ThenValue(nsISerialEventTarget* aResponseTarget,
847 ResolveFunction&& aResolveFunction,
848 RejectFunction&& aRejectFunction, StaticString aCallSite)
849 : ThenValueBase(aResponseTarget, aCallSite) {
850 mResolveFunction.emplace(std::move(aResolveFunction));
851 mRejectFunction.emplace(std::move(aRejectFunction));
852 }
853
854 void Disconnect() override {
855 ThenValueBase::Disconnect();
856
857 // If a Request has been disconnected, we don't guarantee that the
858 // resolve/reject runnable will be dispatched. Destroy our callbacks
859 // now so that any references in closures are released predictable on
860 // the dispatch thread.
861 mResolveFunction.reset();
862 mRejectFunction.reset();
863 }
864
865 protected:
866 MozPromiseBase* CompletionPromise() const override {
867 return mCompletionPromise;
868 }
869
870 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
871 // Note: The usage of InvokeCallbackMethod here requires that
872 // ResolveFunction/RejectFunction are capture-lambdas (i.e. anonymous
873 // classes with ::operator()), since it allows us to share code more
874 // easily. We could fix this if need be, though it's quite easy to work
875 // around by just capturing something.
876 RefPtr<PromiseType> result =
877 aValue.IsResolve()
878 ? InvokeCallbackMethod<SupportChaining, PromiseType>(
879 mResolveFunction.ptr(), &ResolveFunction::operator(),
880 MaybeMove(aValue.ResolveValue()))
881 : InvokeCallbackMethod<SupportChaining, PromiseType>(
882 mRejectFunction.ptr(), &RejectFunction::operator(),
883 MaybeMove(aValue.RejectValue()));
884
885 // Destroy callbacks after invocation so that any references in closures
886 // are released predictably on the dispatch thread. Otherwise, they would
887 // be released on whatever thread last drops its reference to the
888 // ThenValue, which may or may not be ok.
889 mResolveFunction.reset();
890 mRejectFunction.reset();
891
892 MaybeChain<SupportChaining, PromiseType>(result,
893 std::move(mCompletionPromise));
894 }
895
896 private:
897 Maybe<ResolveFunction>
898 mResolveFunction; // Only accessed and deleted on dispatch thread.
899 Maybe<RejectFunction>
900 mRejectFunction; // Only accessed and deleted on dispatch thread.
901 RefPtr<typename PromiseType::Private> mCompletionPromise;
902 };
903
904 template <typename ResolveRejectFunction>
905 class ThenValue<ResolveRejectFunction> : public ThenValueBase {
906 friend class ThenCommand<ThenValue>;
907
908 using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectFunction>>;
909 constexpr static bool SupportChaining = IsMozPromise<R1>;
910
911 // Fall back to MozPromise when promise chaining is not supported to make
912 // code compile.
913 using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
914
915 public:
916 ThenValue(nsISerialEventTarget* aResponseTarget,
917 ResolveRejectFunction&& aResolveRejectFunction,
918 StaticString aCallSite)
919 : ThenValueBase(aResponseTarget, aCallSite) {
920 mResolveRejectFunction.emplace(std::move(aResolveRejectFunction));
921 }
922
923 void Disconnect() override {
924 ThenValueBase::Disconnect();
925
926 // If a Request has been disconnected, we don't guarantee that the
927 // resolve/reject runnable will be dispatched. Destroy our callbacks
928 // now so that any references in closures are released predictable on
929 // the dispatch thread.
930 mResolveRejectFunction.reset();
931 }
932
933 protected:
934 MozPromiseBase* CompletionPromise() const override {
935 return mCompletionPromise;
936 }
937
938 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
939 // Note: The usage of InvokeCallbackMethod here requires that
940 // ResolveRejectFunction is capture-lambdas (i.e. anonymous
941 // classes with ::operator()), since it allows us to share code more
942 // easily. We could fix this if need be, though it's quite easy to work
943 // around by just capturing something.
944 RefPtr<PromiseType> result =
945 InvokeCallbackMethod<SupportChaining, PromiseType>(
946 mResolveRejectFunction.ptr(), &ResolveRejectFunction::operator(),
947 MaybeMove(aValue));
948
949 // Destroy callbacks after invocation so that any references in closures
950 // are released predictably on the dispatch thread. Otherwise, they would
951 // be released on whatever thread last drops its reference to the
952 // ThenValue, which may or may not be ok.
953 mResolveRejectFunction.reset();
954
955 MaybeChain<SupportChaining, PromiseType>(result,
956 std::move(mCompletionPromise));
957 }
958
959 private:
960 Maybe<ResolveRejectFunction>
961 mResolveRejectFunction; // Only accessed and deleted on dispatch
962 // thread.
963 RefPtr<typename PromiseType::Private> mCompletionPromise;
964 };
965
966 template <typename ResolveFunction>
967 class MapValue final : public ThenValueBase {
968 friend class ThenCommand<MapValue>;
969 constexpr static const bool SupportChaining = true;
970 using ResolveValueT_ = std::invoke_result_t<ResolveFunction, ResolveValueT>;
971 using PromiseType = MozPromise<ResolveValueT_, RejectValueT, IsExclusive>;
972
973 public:
974 explicit MapValue(nsISerialEventTarget* aResponseTarget,
975 ResolveFunction&& f, StaticString aCallSite)
976 : ThenValueBase(aResponseTarget, aCallSite),
977 mResolveFunction(Some(std::forward<ResolveFunction>(f))) {}
978
979 protected:
980 void Disconnect() override {
981 ThenValueBase::Disconnect();
982 mResolveFunction.reset();
983 }
984
985 MozPromiseBase* CompletionPromise() const override {
986 return mCompletionPromise;
987 }
988
989 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
990 // Note that promise-chaining is always supported here; this function can
991 // only transform from MozPromise<A, B, k> to MozPromise<A2, B, k>.
992 auto value = MaybeMove(aValue);
993 typename PromiseType::ResolveOrRejectValue output;
994
995 if (value.IsResolve()) {
996 output.SetResolve((*mResolveFunction)(std::move(value.ResolveValue())));
997 } else {
998 output.SetReject(std::move(value.RejectValue()));
999 }
1000
1001 if (mCompletionPromise) {
1002 mCompletionPromise->ResolveOrReject(std::move(output),
1003 ThenValueBase::mCallSite);
1004 }
1005 }
1006
1007 private:
1008 Maybe<ResolveFunction> mResolveFunction;
1009 RefPtr<typename PromiseType::Private> mCompletionPromise;
1010 };
1011
1012 template <typename RejectFunction>
1013 class MapErrValue final : public ThenValueBase {
1014 friend class ThenCommand<MapErrValue>;
1015 constexpr static const bool SupportChaining = true;
1016 using RejectValueT_ = std::invoke_result_t<RejectFunction, RejectValueT>;
1017 using PromiseType = MozPromise<ResolveValueT, RejectValueT_, IsExclusive>;
1018
1019 public:
1020 explicit MapErrValue(nsISerialEventTarget* aResponseTarget,
1021 RejectFunction&& f, StaticString aCallSite)
1022 : ThenValueBase(aResponseTarget, aCallSite),
1023 mRejectFunction(Some(std::forward<RejectFunction>(f))) {}
1024
1025 protected:
1026 void Disconnect() override {
1027 ThenValueBase::Disconnect();
1028 mRejectFunction.reset();
1029 }
1030
1031 MozPromiseBase* CompletionPromise() const override {
1032 return mCompletionPromise;
1033 }
1034
1035 void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
1036 // Note that promise-chaining is always supported here; this function can
1037 // only transform from MozPromise<A, B, k> to MozPromise<A, B2, k>.
1038 auto value = MaybeMove(aValue);
1039 typename PromiseType::ResolveOrRejectValue output;
1040
1041 if (value.IsResolve()) {
1042 output.SetResolve(std::move(value.ResolveValue()));
1043 } else {
1044 output.SetReject((*mRejectFunction)(std::move(value.RejectValue())));
1045 }
1046
1047 if (mCompletionPromise) {
1048 mCompletionPromise->ResolveOrReject(std::move(output),
1049 ThenValueBase::mCallSite);
1050 }
1051 }
1052
1053 private:
1054 Maybe<RejectFunction> mRejectFunction;
1055 RefPtr<typename PromiseType::Private> mCompletionPromise;
1056 };
1057
1058 public:
1059 void ThenInternal(already_AddRefed<ThenValueBase> aThenValue,
1060 StaticString aCallSite) {
1061 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1062 mMagic3 == sMagic && mMagic4 == &mMutex);
1063 RefPtr<ThenValueBase> thenValue = aThenValue;
1064 MutexAutoLock lock(mMutex);
1065 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"
, 1067); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1067); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1066 !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"
, 1067); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1067); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1067 "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"
, 1067); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1067); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1068 mHaveRequest = true;
1069 PROMISE_LOG("%s invoking Then() [this=%p, aThenValue=%p, isPending=%d]",
1070 aCallSite.get(), this, thenValue.get(), (int)IsPending());
1071 if (!IsPending()) {
1072 thenValue->Dispatch(this);
1073 } else {
1074 mThenValues.AppendElement(thenValue.forget());
1075 }
1076 }
1077
1078 protected:
1079 /*
1080 * A command object to store all information needed to make a request to the
1081 * promise. This allows us to delay the request until further use is known
1082 * (whether it is ->Then() again for more promise chaining or ->Track() to
1083 * terminate chaining and issue the request).
1084 *
1085 * This allows a unified syntax for promise chaining and disconnection, and
1086 * feels more like its JS counterpart.
1087 *
1088 * Note that a ThenCommand is always exclusive, even if its source or result
1089 * promises are not. To attach multiple continuations, explicitly convert it
1090 * to a promise first.
1091 */
1092 template <typename ThenValueType>
1093 class MOZ_TEMPORARY_CLASS ThenCommand {
1094 // Allow Promise1::ThenCommand to access the private constructor
1095 // Promise2::ThenCommand(ThenCommand&&).
1096 template <typename, typename, bool>
1097 friend class MozPromise;
1098
1099 using PromiseType = typename ThenValueType::PromiseType;
1100 using Private = typename PromiseType::Private;
1101
1102 ThenCommand(StaticString aCallSite,
1103 already_AddRefed<ThenValueType> aThenValue,
1104 MozPromise* aReceiver)
1105 : mCallSite(aCallSite), mThenValue(aThenValue), mReceiver(aReceiver) {}
1106
1107 ThenCommand(ThenCommand&& aOther) noexcept = default;
1108
1109 public:
1110 ~ThenCommand() {
1111 // Issue the request now if the return value of Then() is not used.
1112 if (mThenValue) {
41
Taking false branch
1113 mReceiver->ThenInternal(mThenValue.forget(), mCallSite);
1114 }
1115 }
42
Calling '~RefPtr'
1116
1117 // Allow RefPtr<MozPromise> p = somePromise->Then();
1118 // p->Then(thread1, ...);
1119 // p->Then(thread2, ...);
1120 operator RefPtr<PromiseType>() {
1121 static_assert(
1122 ThenValueType::SupportChaining,
1123 "The resolve/reject callback needs to return a RefPtr<MozPromise> "
1124 "in order to do promise chaining.");
1125
1126 // mCompletionPromise must be created before ThenInternal() to avoid race.
1127 RefPtr<Private> p =
1128 new Private("<completion promise>", true /* aIsCompletionPromise */);
1129 mThenValue->mCompletionPromise = p;
1130 // Note ThenInternal() might nullify mCompletionPromise before return.
1131 // So we need to return p instead of mCompletionPromise.
1132 mReceiver->ThenInternal(mThenValue.forget(), mCallSite);
1133 return p;
1134 }
1135
1136 template <typename... Ts>
1137 auto Then(Ts&&... aArgs) -> decltype(std::declval<PromiseType>().Then(
1138 std::forward<Ts>(aArgs)...)) {
1139 return static_cast<RefPtr<PromiseType>>(*this)->Then(
1140 std::forward<Ts>(aArgs)...);
1141 }
1142
1143 template <typename... Ts>
1144 auto Map(Ts&&... aArgs) -> decltype(std::declval<PromiseType>().Map(
1145 std::forward<Ts>(aArgs)...)) {
1146 return static_cast<RefPtr<PromiseType>>(*this)->Map(
1147 std::forward<Ts>(aArgs)...);
1148 }
1149
1150 template <typename... Ts>
1151 auto MapErr(Ts&&... aArgs) -> decltype(std::declval<PromiseType>().MapErr(
1152 std::forward<Ts>(aArgs)...)) {
1153 return static_cast<RefPtr<PromiseType>>(*this)->MapErr(
1154 std::forward<Ts>(aArgs)...);
1155 }
1156
1157 void Track(MozPromiseRequestHolder<MozPromise>& aRequestHolder) {
1158 aRequestHolder.Track(do_AddRef(mThenValue));
1159 mReceiver->ThenInternal(mThenValue.forget(), mCallSite);
1160 }
1161
1162 // Allow calling ->Then() again for more promise chaining or ->Track() to
1163 // end chaining and track the request for future disconnection.
1164 ThenCommand* operator->() { return this; }
1165
1166 private:
1167 StaticString mCallSite;
1168 RefPtr<ThenValueType> mThenValue;
1169 RefPtr<MozPromise> mReceiver;
1170 };
1171
1172 public:
1173 template <typename ThisType, typename... Methods,
1174 typename ThenValueType = ThenValue<ThisType*, Methods...>,
1175 typename ReturnType = ThenCommand<ThenValueType>>
1176 ReturnType Then(nsISerialEventTarget* aResponseTarget, StaticString aCallSite,
1177 ThisType* aThisVal, Methods... aMethods) {
1178 RefPtr<ThenValueType> thenValue =
1179 new ThenValueType(aResponseTarget, aThisVal, aMethods..., aCallSite);
1180 return ReturnType(aCallSite, thenValue.forget(), this);
1181 }
1182
1183 template <typename... Functions,
1184 typename ThenValueType = ThenValue<Functions...>,
1185 typename ReturnType = ThenCommand<ThenValueType>>
1186 ReturnType Then(nsISerialEventTarget* aResponseTarget, StaticString aCallSite,
1187 Functions&&... aFunctions) {
1188 RefPtr<ThenValueType> thenValue =
1189 new ThenValueType(aResponseTarget, std::move(aFunctions)..., aCallSite);
1190 return ReturnType(aCallSite, thenValue.forget(), this);
1191 }
1192
1193 // Shorthand for a `Then` which simply forwards the reject-value, but performs
1194 // some additional work with the resolve-value.
1195 template <typename Function>
1196 auto Map(nsISerialEventTarget* aResponseTarget, StaticString aCallSite,
1197 Function&& function) {
1198 RefPtr<MapValue<Function>> thenValue = new MapValue<Function>(
1199 aResponseTarget, std::forward<Function>(function), aCallSite);
1200 return ThenCommand<MapValue<Function>>(aCallSite, thenValue.forget(), this);
1201 }
1202
1203 // Shorthand for a `Then` which simply forwards the resolve-value, but
1204 // performs some additional work with the reject-value.
1205 template <typename Function>
1206 auto MapErr(nsISerialEventTarget* aResponseTarget, StaticString aCallSite,
1207 Function&& function) {
1208 RefPtr<MapErrValue<Function>> thenValue = new MapErrValue<Function>(
1209 aResponseTarget, std::forward<Function>(function), aCallSite);
1210 return ThenCommand<MapErrValue<Function>>(aCallSite, thenValue.forget(),
1211 this);
1212 }
1213
1214 void ChainTo(already_AddRefed<Private> aChainedPromise,
1215 StaticString aCallSite) {
1216 MutexAutoLock lock(mMutex);
1217 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"
, 1219); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1219); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1218 !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"
, 1219); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1219); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1219 "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"
, 1219); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsExclusive || !mHaveRequest"
") (" "Using an exclusive promise in a non-exclusive fashion"
")"); do { MOZ_CrashSequence(__null, 1219); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1220 mHaveRequest = true;
1221 RefPtr<Private> chainedPromise = aChainedPromise;
1222 PROMISE_LOG(
1223 "%s invoking Chain() [this=%p, chainedPromise=%p, isPending=%d]",
1224 aCallSite.get(), this, chainedPromise.get(), (int)IsPending());
1225
1226 // We want to use the same type of dispatching method with the chained
1227 // promises.
1228
1229 // We need to ensure that the UseSynchronousTaskDispatch branch isn't taken
1230 // at compilation time to ensure we're not triggering the static_assert in
1231 // UseSynchronousTaskDispatch method. if constexpr (IsExclusive) ensures
1232 // that.
1233 if (mUseDirectTaskDispatch) {
1234 chainedPromise->UseDirectTaskDispatch(aCallSite);
1235 } else if constexpr (IsExclusive) {
1236 if (mUseSynchronousTaskDispatch) {
1237 chainedPromise->UseSynchronousTaskDispatch(aCallSite);
1238 }
1239 } else {
1240 chainedPromise->SetTaskPriority(mPriority, aCallSite);
1241 }
1242
1243 if (!IsPending()) {
1244 ForwardTo(chainedPromise);
1245 } else {
1246 mChainedPromises.AppendElement(chainedPromise);
1247 }
1248 }
1249
1250#ifdef MOZ_WIDGET_ANDROID
1251 // Creates a C++ MozPromise from its Java counterpart, GeckoResult.
1252 [[nodiscard]] static RefPtr<MozPromise> FromGeckoResult(
1253 java::GeckoResult::Param aGeckoResult) {
1254 using jni::GeckoResultCallback;
1255 RefPtr<Private> p = new Private("GeckoResult Glue", false);
1256 auto resolve = GeckoResultCallback::CreateAndAttach<ResolveValueType>(
1257 [p](ResolveValueType&& aArg) {
1258 p->Resolve(MaybeMove(aArg), __func__);
1259 });
1260 auto reject = GeckoResultCallback::CreateAndAttach<RejectValueType>(
1261 [p](RejectValueType&& aArg) { p->Reject(MaybeMove(aArg), __func__); });
1262 aGeckoResult->NativeThen(resolve, reject);
1263 return p;
1264 }
1265#endif
1266
1267 // Note we expose the function AssertIsDead() instead of IsDead() since
1268 // checking IsDead() is a data race in the situation where the request is not
1269 // dead. Therefore we enforce the form |Assert(IsDead())| by exposing
1270 // AssertIsDead() only.
1271 void AssertIsDead() override {
1272 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1273 mMagic3 == sMagic && mMagic4 == &mMutex);
1274 MutexAutoLock lock(mMutex);
1275 for (auto&& then : mThenValues) {
1276 then->AssertIsDead();
1277 }
1278 for (auto&& chained : mChainedPromises) {
1279 chained->AssertIsDead();
1280 }
1281 }
1282
1283 protected:
1284 // NOTE: Methods like `IsPending()` and `Value()` are intentionally marked as
1285 // `protected`, as they are not safe to call from outside of the MozPromise
1286 // code. The only way to inspect the state of a MozPromise is intentionally
1287 // to call `->Then` on the promise, and receive an async callback.
1288 //
1289 // MozPromise has somewhat complex locking and thread safety properties which
1290 // can't be extended outside of the code in this file.
1291 bool IsPending() const { return mValue.IsNothing(); }
1292
1293 ResolveOrRejectValue& Value() {
1294 // This method should only be called once the value has stabilized. As
1295 // such, we don't need to acquire the lock here.
1296 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"
, 1296); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!IsPending()"
")"); do { MOZ_CrashSequence(__null, 1296); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1297 return mValue;
1298 }
1299
1300 void DispatchAll() {
1301 mMutex.AssertCurrentThreadOwns();
1302 for (auto&& thenValue : mThenValues) {
1303 thenValue->Dispatch(this);
1304 }
1305 mThenValues.Clear();
1306
1307 for (auto&& chainedPromise : mChainedPromises) {
1308 ForwardTo(chainedPromise);
1309 }
1310 mChainedPromises.Clear();
1311 }
1312
1313 void ForwardTo(Private* aOther) {
1314 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"
, 1314); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsPending()"
")"); do { MOZ_CrashSequence(__null, 1314); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1315 if (mValue.IsResolve()) {
1316 aOther->Resolve(MaybeMove(mValue.ResolveValue()), "<chained promise>");
1317 } else {
1318 aOther->Reject(MaybeMove(mValue.RejectValue()), "<chained promise>");
1319 }
1320 }
1321
1322 virtual ~MozPromise() {
1323 PROMISE_LOG("MozPromise::~MozPromise [this=%p]", this);
1324 AssertIsDead();
1325 // We can't guarantee a completion promise will always be revolved or
1326 // rejected since ResolveOrRejectRunnable might not run when dispatch fails.
1327 if (!mIsCompletionPromise) {
1328 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"
, 1328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsPending()"
")"); do { MOZ_CrashSequence(__null, 1328); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1329 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"
, 1329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mThenValues.IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1329); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1330 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"
, 1330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChainedPromises.IsEmpty()"
")"); do { MOZ_CrashSequence(__null, 1330); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1331 }
1332#ifdef PROMISE_DEBUG
1333 mMagic1 = 0;
1334 mMagic2 = 0;
1335 mMagic3 = 0;
1336 mMagic4 = nullptr;
1337#endif
1338 };
1339
1340 StaticString mCreationSite; // For logging and profiling
1341 Mutex mMutex MOZ_UNANNOTATED;
1342 ResolveOrRejectValue mValue;
1343 bool mUseSynchronousTaskDispatch = false;
1344 bool mUseDirectTaskDispatch = false;
1345 uint32_t mPriority = nsIRunnablePriority::PRIORITY_NORMAL;
1346#ifdef PROMISE_DEBUG
1347 uint32_t mMagic1 = sMagic;
1348#endif
1349 // Try shows we never have more than 3 elements when IsExclusive is false.
1350 // So '3' is a good value to avoid heap allocation in most cases.
1351 AutoTArray<RefPtr<ThenValueBase>, IsExclusive ? 1 : 3> mThenValues;
1352#ifdef PROMISE_DEBUG
1353 uint32_t mMagic2 = sMagic;
1354#endif
1355 nsTArray<RefPtr<Private>> mChainedPromises;
1356#ifdef PROMISE_DEBUG
1357 uint32_t mMagic3 = sMagic;
1358#endif
1359 bool mHaveRequest;
1360 const bool mIsCompletionPromise;
1361#ifdef PROMISE_DEBUG
1362 void* mMagic4;
1363#endif
1364};
1365
1366template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
1367class MozPromise<ResolveValueT, RejectValueT, IsExclusive>::Private
1368 : public MozPromise<ResolveValueT, RejectValueT, IsExclusive> {
1369 public:
1370 explicit Private(StaticString aCreationSite,
1371 bool aIsCompletionPromise = false)
1372 : MozPromise(aCreationSite, aIsCompletionPromise) {}
1373
1374 template <typename ResolveValueT_>
1375 void Resolve(ResolveValueT_&& aResolveValue, StaticString aResolveSite) {
1376 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1377 mMagic3 == sMagic && mMagic4 == &mMutex);
1378 MutexAutoLock lock(mMutex);
1379 PROMISE_LOG("%s resolving MozPromise (%p created at %s)",
1380 aResolveSite.get(), this, mCreationSite.get());
1381 if (!IsPending()) {
1382 PROMISE_LOG(
1383 "%s ignored already resolved or rejected MozPromise (%p created at "
1384 "%s)",
1385 aResolveSite.get(), this, mCreationSite.get());
1386 return;
1387 }
1388 mValue.SetResolve(std::forward<ResolveValueT_>(aResolveValue));
1389 DispatchAll();
1390 }
1391
1392 template <typename RejectValueT_>
1393 void Reject(RejectValueT_&& aRejectValue, StaticString aRejectSite) {
1394 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1395 mMagic3 == sMagic && mMagic4 == &mMutex);
1396 MutexAutoLock lock(mMutex);
1397 PROMISE_LOG("%s rejecting MozPromise (%p created at %s)", aRejectSite.get(),
1398 this, mCreationSite.get());
1399 if (!IsPending()) {
1400 PROMISE_LOG(
1401 "%s ignored already resolved or rejected MozPromise (%p created at "
1402 "%s)",
1403 aRejectSite.get(), this, mCreationSite.get());
1404 return;
1405 }
1406 mValue.SetReject(std::forward<RejectValueT_>(aRejectValue));
1407 DispatchAll();
1408 }
1409
1410 template <typename ResolveOrRejectValue_>
1411 void ResolveOrReject(ResolveOrRejectValue_&& aValue, StaticString aSite) {
1412 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1413 mMagic3 == sMagic && mMagic4 == &mMutex);
1414 MutexAutoLock lock(mMutex);
1415 PROMISE_LOG("%s resolveOrRejecting MozPromise (%p created at %s)",
1416 aSite.get(), this, mCreationSite.get());
1417 if (!IsPending()) {
1418 PROMISE_LOG(
1419 "%s ignored already resolved or rejected MozPromise (%p created at "
1420 "%s)",
1421 aSite.get(), this, mCreationSite.get());
1422 return;
1423 }
1424 mValue = std::forward<ResolveOrRejectValue_>(aValue);
1425 DispatchAll();
1426 }
1427
1428 // If the caller and target are both on the same thread, run the the resolve
1429 // or reject callback synchronously. Otherwise, the task will be dispatched
1430 // via the target Dispatch method.
1431 void UseSynchronousTaskDispatch(const char* aSite) {
1432 static_assert(
1433 IsExclusive,
1434 "Synchronous dispatch can only be used with exclusive promises");
1435 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1436 mMagic3 == sMagic && mMagic4 == &mMutex);
1437 MutexAutoLock lock(mMutex);
1438 PROMISE_LOG("%s UseSynchronousTaskDispatch MozPromise (%p created at %s)",
1439 aSite, this, mCreationSite.get());
1440 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"
, 1442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1442
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1441 "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"
, 1442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1442
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1442 "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"
, 1442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1442
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1443 mUseSynchronousTaskDispatch = true;
1444 }
1445
1446 // If the caller and target are both on the same thread, run the
1447 // resolve/reject callback off the direct task queue instead. This avoids a
1448 // full trip to the back of the event queue for each additional asynchronous
1449 // step when using MozPromise, and is similar (but not identical to) the
1450 // microtask semantics of JS promises.
1451 void UseDirectTaskDispatch(const char* aSite) {
1452 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1453 mMagic3 == sMagic && mMagic4 == &mMutex);
1454 MutexAutoLock lock(mMutex);
1455 PROMISE_LOG("%s UseDirectTaskDispatch MozPromise (%p created at %s)", aSite,
1456 this, mCreationSite.get());
1457 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"
, 1459); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1459
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1458 "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"
, 1459); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1459
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1459 "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"
, 1459); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1459
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1460 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"
, 1461); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseSynchronousTaskDispatch"
") (" "Promise already set for synchronous dispatch" ")"); do
{ MOZ_CrashSequence(__null, 1461); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1461 "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"
, 1461); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseSynchronousTaskDispatch"
") (" "Promise already set for synchronous dispatch" ")"); do
{ MOZ_CrashSequence(__null, 1461); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1462 mUseDirectTaskDispatch = true;
1463 }
1464
1465 // If the resolve/reject will be handled on a thread supporting priorities,
1466 // one may want to tweak the priority of the task by passing a
1467 // nsIRunnablePriority::PRIORITY_* to SetTaskPriority.
1468 void SetTaskPriority(uint32_t aPriority, const char* aSite) {
1469 PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic &&
1470 mMagic3 == sMagic && mMagic4 == &mMutex);
1471 MutexAutoLock lock(mMutex);
1472 PROMISE_LOG("%s TaskPriority MozPromise (%p created at %s)", aSite, this,
1473 mCreationSite.get());
1474 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"
, 1476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1476
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1475 "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"
, 1476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1476
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1476 "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"
, 1476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPending()"
") (" "A Promise must not have been already resolved or rejected to "
"set dispatch state" ")"); do { MOZ_CrashSequence(__null, 1476
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1477 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"
, 1478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseSynchronousTaskDispatch"
") (" "Promise already set for synchronous dispatch" ")"); do
{ MOZ_CrashSequence(__null, 1478); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1478 "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"
, 1478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseSynchronousTaskDispatch"
") (" "Promise already set for synchronous dispatch" ")"); do
{ MOZ_CrashSequence(__null, 1478); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1479 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"
, 1480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseDirectTaskDispatch"
") (" "Promise already set for direct dispatch" ")"); do { MOZ_CrashSequence
(__null, 1480); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1480 "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"
, 1480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mUseDirectTaskDispatch"
") (" "Promise already set for direct dispatch" ")"); do { MOZ_CrashSequence
(__null, 1480); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1481 mPriority = aPriority;
1482 }
1483};
1484
1485// A generic promise type that does the trick for simple use cases.
1486//
1487// Vaguely deprecated: prefer explicitly naming the resolve- and reject-type.
1488// Additionally, prefer `mozilla::Ok` as the resolve-type if the boolean's value
1489// is irrelevant.
1490using GenericPromise = MozPromise<bool, nsresult, /* IsExclusive = */ true>;
1491
1492// A generic, non-exclusive promise type that does the trick for simple use
1493// cases.
1494//
1495// Vaguely deprecated, as above.
1496using GenericNonExclusivePromise =
1497 MozPromise<bool, nsresult, /* IsExclusive = */ false>;
1498
1499/*
1500 * Class to encapsulate a promise for a particular role. Use this as the member
1501 * variable for a class whose method returns a promise.
1502 */
1503template <typename PromiseType, typename ImplType>
1504class MozPromiseHolderBase {
1505 public:
1506 MozPromiseHolderBase() = default;
1507
1508 MozPromiseHolderBase(MozPromiseHolderBase&& aOther) noexcept = default;
1509 MozPromiseHolderBase& operator=(MozPromiseHolderBase&& aOther) noexcept =
1510 default;
1511
1512 ~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"
, 1512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPromise" ")"
); do { MOZ_CrashSequence(__null, 1512); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; }
1513
1514 already_AddRefed<PromiseType> Ensure(StaticString aMethodName) {
1515 static_cast<ImplType*>(this)->Check();
1516 if (!mPromise) {
1517 mPromise = new (typename PromiseType::Private)(aMethodName);
1518 }
1519 RefPtr<PromiseType> p = mPromise.get();
1520 return p.forget();
1521 }
1522
1523 bool IsEmpty() const {
1524 static_cast<const ImplType*>(this)->Check();
1525 return !mPromise;
1526 }
1527
1528 already_AddRefed<typename PromiseType::Private> Steal() {
1529 static_cast<ImplType*>(this)->Check();
1530 return mPromise.forget();
1531 }
1532
1533 template <typename ResolveValueType_>
1534 void Resolve(ResolveValueType_&& aResolveValue, StaticString aMethodName) {
1535 static_assert(std::is_convertible_v<ResolveValueType_,
1536 typename PromiseType::ResolveValueType>,
1537 "Resolve() argument must be implicitly convertible to "
1538 "MozPromise's ResolveValueT");
1539
1540 static_cast<ImplType*>(this)->Check();
1541 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"
, 1541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1542 mPromise->Resolve(std::forward<ResolveValueType_>(aResolveValue),
1543 aMethodName);
1544 mPromise = nullptr;
1545 }
1546
1547 template <typename ResolveValueType_>
1548 void ResolveIfExists(ResolveValueType_&& aResolveValue,
1549 StaticString aMethodName) {
1550 if (!IsEmpty()) {
1551 Resolve(std::forward<ResolveValueType_>(aResolveValue), aMethodName);
1552 }
1553 }
1554
1555 template <typename RejectValueType_>
1556 void Reject(RejectValueType_&& aRejectValue, StaticString aMethodName) {
1557 static_assert(std::is_convertible_v<RejectValueType_,
1558 typename PromiseType::RejectValueType>,
1559 "Reject() argument must be implicitly convertible to "
1560 "MozPromise's RejectValueT");
1561
1562 static_cast<ImplType*>(this)->Check();
1563 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"
, 1563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1563); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1564 mPromise->Reject(std::forward<RejectValueType_>(aRejectValue), aMethodName);
1565 mPromise = nullptr;
1566 }
1567
1568 template <typename RejectValueType_>
1569 void RejectIfExists(RejectValueType_&& aRejectValue,
1570 StaticString aMethodName) {
1571 if (!IsEmpty()) {
1572 Reject(std::forward<RejectValueType_>(aRejectValue), aMethodName);
1573 }
1574 }
1575
1576 template <typename ResolveOrRejectValueType_>
1577 void ResolveOrReject(ResolveOrRejectValueType_&& aValue,
1578 StaticString aMethodName) {
1579 static_cast<ImplType*>(this)->Check();
1580 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"
, 1580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1580); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1581 mPromise->ResolveOrReject(std::forward<ResolveOrRejectValueType_>(aValue),
1582 aMethodName);
1583 mPromise = nullptr;
1584 }
1585
1586 template <typename ResolveOrRejectValueType_>
1587 void ResolveOrRejectIfExists(ResolveOrRejectValueType_&& aValue,
1588 StaticString aMethodName) {
1589 if (!IsEmpty()) {
1590 ResolveOrReject(std::forward<ResolveOrRejectValueType_>(aValue),
1591 aMethodName);
1592 }
1593 }
1594
1595 void UseSynchronousTaskDispatch(const char* aSite) {
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->UseSynchronousTaskDispatch(aSite);
1598 }
1599
1600 void UseDirectTaskDispatch(const char* aSite) {
1601 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"
, 1601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1601); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1602 mPromise->UseDirectTaskDispatch(aSite);
1603 }
1604
1605 void SetTaskPriority(uint32_t aPriority, const char* aSite) {
1606 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"
, 1606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPromise" ")"
); do { MOZ_CrashSequence(__null, 1606); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1607 mPromise->SetTaskPriority(aPriority, aSite);
1608 }
1609
1610 private:
1611 RefPtr<typename PromiseType::Private> mPromise;
1612};
1613
1614template <typename PromiseType>
1615class MozPromiseHolder
1616 : public MozPromiseHolderBase<PromiseType, MozPromiseHolder<PromiseType>> {
1617 public:
1618 using MozPromiseHolderBase<
1619 PromiseType, MozPromiseHolder<PromiseType>>::MozPromiseHolderBase;
1620 static constexpr void Check() {};
1621};
1622
1623template <typename PromiseType>
1624class MozMonitoredPromiseHolder
1625 : public MozPromiseHolderBase<PromiseType,
1626 MozMonitoredPromiseHolder<PromiseType>> {
1627 public:
1628 // Provide a Monitor that should always be held when accessing this instance.
1629 explicit MozMonitoredPromiseHolder(Monitor* const aMonitor)
1630 : mMonitor(aMonitor) {
1631 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"
, 1631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMonitor" ")"
); do { MOZ_CrashSequence(__null, 1631); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1632 }
1633
1634 MozMonitoredPromiseHolder(MozMonitoredPromiseHolder&& aOther) = delete;
1635 MozMonitoredPromiseHolder& operator=(MozMonitoredPromiseHolder&& aOther) =
1636 delete;
1637
1638 void Check() const { mMonitor->AssertCurrentThreadOwns(); }
1639
1640 private:
1641 Monitor* const mMonitor;
1642};
1643
1644/*
1645 * Class to encapsulate a MozPromise::Request reference. Use this as the member
1646 * variable for a class waiting on a MozPromise.
1647 */
1648template <typename PromiseType>
1649class MozPromiseRequestHolder {
1650 public:
1651 MozPromiseRequestHolder() = default;
1652 ~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"
, 1652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRequest" ")"
); do { MOZ_CrashSequence(__null, 1652); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; }
1653
1654 void Track(already_AddRefed<typename PromiseType::Request> aRequest) {
1655 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"
, 1655); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!Exists()"
")"); do { MOZ_CrashSequence(__null, 1655); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1656 mRequest = aRequest;
1657 }
1658
1659 void Complete() {
1660 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"
, 1660); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "Exists()"
")"); do { MOZ_CrashSequence(__null, 1660); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1661 mRequest = nullptr;
1662 }
1663
1664 // Disconnects and forgets an outstanding promise. The resolve/reject methods
1665 // will never be called.
1666 void Disconnect() {
1667 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"
, 1667); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Exists()" ")"
); do { MOZ_CrashSequence(__null, 1667); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1668 RefPtr request = std::move(mRequest);
1669 request->Disconnect();
1670 }
1671
1672 void DisconnectIfExists() {
1673 if (Exists()) {
1674 Disconnect();
1675 }
1676 }
1677
1678 bool Exists() const { return !!mRequest; }
1679
1680 private:
1681 RefPtr<typename PromiseType::Request> mRequest;
1682};
1683
1684// Asynchronous Potentially-Cross-Thread Method Calls.
1685//
1686// This machinery allows callers to schedule a promise-returning function
1687// (a method and object, or a function object like a lambda) to be invoked
1688// asynchronously on a given thread, while at the same time receiving a
1689// promise upon which to invoke Then() immediately. InvokeAsync dispatches a
1690// task to invoke the function on the proper thread and also chain the
1691// resulting promise to the one that the caller received, so that resolve/
1692// reject values are forwarded through.
1693
1694namespace detail {
1695
1696// Non-templated base class to allow us to use MOZ_COUNT_{C,D}TOR, which cause
1697// assertions when used on templated types.
1698class MethodCallBase {
1699 public:
1700 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); }
1701 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); }
1702};
1703
1704template <typename PromiseType, typename MethodType, typename ThisType,
1705 typename... Storages>
1706class MethodCall : public MethodCallBase {
1707 public:
1708 template <typename... Args>
1709 MethodCall(MethodType aMethod, ThisType* aThisVal, Args&&... aArgs)
1710 : mMethod(aMethod),
1711 mThisVal(aThisVal),
1712 mArgs(std::forward<Args>(aArgs)...) {
1713 static_assert(sizeof...(Storages) == sizeof...(Args),
1714 "Storages and Args should have equal sizes");
1715 }
1716
1717 RefPtr<PromiseType> Invoke() { return mArgs.apply(mThisVal.get(), mMethod); }
1718
1719 private:
1720 MethodType mMethod;
1721 RefPtr<ThisType> mThisVal;
1722 RunnableMethodArguments<Storages...> mArgs;
1723};
1724
1725template <typename PromiseType, typename MethodType, typename ThisType,
1726 typename... Storages>
1727class ProxyRunnable : public CancelableRunnable {
1728 public:
1729 ProxyRunnable(
1730 typename PromiseType::Private* aProxyPromise,
1731 MethodCall<PromiseType, MethodType, ThisType, Storages...>* aMethodCall)
1732 : CancelableRunnable("detail::ProxyRunnable"),
1733 mProxyPromise(aProxyPromise),
1734 mMethodCall(aMethodCall) {}
1735
1736 NS_IMETHODvirtual nsresult Run() override {
1737 RefPtr<PromiseType> p = mMethodCall->Invoke();
1738 mMethodCall = nullptr;
1739 p->ChainTo(mProxyPromise.forget(), "<Proxy Promise>");
1740 return NS_OK;
1741 }
1742
1743 nsresult Cancel() override { return Run(); }
1744
1745 private:
1746 RefPtr<typename PromiseType::Private> mProxyPromise;
1747 UniquePtr<MethodCall<PromiseType, MethodType, ThisType, Storages...>>
1748 mMethodCall;
1749};
1750
1751template <typename... Storages, typename PromiseType, typename ThisType,
1752 typename... ArgTypes, typename... ActualArgTypes>
1753RefPtr<PromiseType> InvokeAsyncImpl(
1754 nsISerialEventTarget* aTarget, ThisType* aThisVal, StaticString aCallerName,
1755 RefPtr<PromiseType> (ThisType::*aMethod)(ArgTypes...),
1756 ActualArgTypes&&... aArgs) {
1757 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"
, 1757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTarget" ")"
); do { MOZ_CrashSequence(__null, 1757); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1758
1759 typedef RefPtr<PromiseType> (ThisType::*MethodType)(ArgTypes...);
1760 typedef detail::MethodCall<PromiseType, MethodType, ThisType, Storages...>
1761 MethodCallType;
1762 typedef detail::ProxyRunnable<PromiseType, MethodType, ThisType, Storages...>
1763 ProxyRunnableType;
1764
1765 MethodCallType* methodCall = new MethodCallType(
1766 aMethod, aThisVal, std::forward<ActualArgTypes>(aArgs)...);
1767 RefPtr<typename PromiseType::Private> p =
1768 new (typename PromiseType::Private)(aCallerName);
1769 RefPtr<ProxyRunnableType> r = new ProxyRunnableType(p, methodCall);
1770 aTarget->Dispatch(r.forget());
1771 return p;
1772}
1773
1774constexpr bool Any() { return false; }
1775
1776template <typename T1>
1777constexpr bool Any(T1 a) {
1778 return static_cast<bool>(a);
1779}
1780
1781template <typename T1, typename... Ts>
1782constexpr bool Any(T1 a, Ts... aOthers) {
1783 return a || Any(aOthers...);
1784}
1785
1786} // namespace detail
1787
1788// InvokeAsync with explicitly-specified storages.
1789// See ParameterStorage in nsThreadUtils.h for help.
1790template <typename... Storages, typename PromiseType, typename ThisType,
1791 typename... ArgTypes, typename... ActualArgTypes,
1792 std::enable_if_t<sizeof...(Storages) != 0, int> = 0>
1793RefPtr<PromiseType> InvokeAsync(
1794 nsISerialEventTarget* aTarget, ThisType* aThisVal, StaticString aCallerName,
1795 RefPtr<PromiseType> (ThisType::*aMethod)(ArgTypes...),
1796 ActualArgTypes&&... aArgs) {
1797 static_assert(
1798 sizeof...(Storages) == sizeof...(ArgTypes),
1799 "Provided Storages and method's ArgTypes should have equal sizes");
1800 static_assert(sizeof...(Storages) == sizeof...(ActualArgTypes),
1801 "Provided Storages and ActualArgTypes should have equal sizes");
1802 return detail::InvokeAsyncImpl<Storages...>(
1803 aTarget, aThisVal, aCallerName, aMethod,
1804 std::forward<ActualArgTypes>(aArgs)...);
1805}
1806
1807// InvokeAsync with no explicitly-specified storages, will copy arguments and
1808// then move them out of the runnable into the target method parameters.
1809template <typename... Storages, typename PromiseType, typename ThisType,
1810 typename... ArgTypes, typename... ActualArgTypes,
1811 std::enable_if_t<sizeof...(Storages) == 0, int> = 0>
1812RefPtr<PromiseType> InvokeAsync(
1813 nsISerialEventTarget* aTarget, ThisType* aThisVal, StaticString aCallerName,
1814 RefPtr<PromiseType> (ThisType::*aMethod)(ArgTypes...),
1815 ActualArgTypes&&... aArgs) {
1816 static_assert(
1817 !detail::Any(
1818 std::is_pointer_v<std::remove_reference_t<ActualArgTypes>>...),
1819 "Cannot pass pointer types through InvokeAsync, Storages must be "
1820 "provided");
1821 static_assert(sizeof...(ArgTypes) == sizeof...(ActualArgTypes),
1822 "Method's ArgTypes and ActualArgTypes should have equal sizes");
1823 return detail::InvokeAsyncImpl<
1824 StoreCopyPassByRRef<std::decay_t<ActualArgTypes>>...>(
1825 aTarget, aThisVal, aCallerName, aMethod,
1826 std::forward<ActualArgTypes>(aArgs)...);
1827}
1828
1829namespace detail {
1830
1831template <typename Function, typename PromiseType>
1832class ProxyFunctionRunnable : public CancelableRunnable {
1833 using FunctionStorage = std::decay_t<Function>;
1834
1835 public:
1836 template <typename F>
1837 ProxyFunctionRunnable(typename PromiseType::Private* aProxyPromise,
1838 F&& aFunction)
1839 : CancelableRunnable("detail::ProxyFunctionRunnable"),
1840 mProxyPromise(aProxyPromise),
1841 mFunction(new FunctionStorage(std::forward<F>(aFunction))) {}
1842
1843 NS_IMETHODvirtual nsresult Run() override {
1844 RefPtr<PromiseType> p = (*mFunction)();
1845 mFunction = nullptr;
1846 p->ChainTo(mProxyPromise.forget(), "<Proxy Promise>");
1847 return NS_OK;
1848 }
1849
1850 nsresult Cancel() override { return Run(); }
1851
1852 private:
1853 RefPtr<typename PromiseType::Private> mProxyPromise;
1854 UniquePtr<FunctionStorage> mFunction;
1855};
1856
1857template <typename T>
1858constexpr static bool IsRefPtrMozPromise = false;
1859template <typename T, typename U, bool B>
1860constexpr static bool IsRefPtrMozPromise<RefPtr<MozPromise<T, U, B>>> = true;
1861
1862} // namespace detail
1863
1864// Invoke a function object (e.g., lambda) asynchronously.
1865// Return a promise that the function should eventually resolve or reject.
1866template <typename Function>
1867auto InvokeAsync(nsISerialEventTarget* aTarget, StaticString aCallerName,
1868 Function&& aFunction) -> decltype(aFunction()) {
1869 static_assert(!std::is_lvalue_reference_v<Function>,
1870 "Function object must not be passed by lvalue-ref (to avoid "
1871 "unplanned copies); Consider move()ing the object.");
1872
1873 static_assert(detail::IsRefPtrMozPromise<decltype(aFunction())>,
1874 "Function object must return RefPtr<MozPromise>");
1875 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"
, 1875); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTarget" ")"
); do { MOZ_CrashSequence(__null, 1875); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1876 typedef RemoveSmartPointer<decltype(aFunction())> PromiseType;
1877 typedef detail::ProxyFunctionRunnable<Function, PromiseType>
1878 ProxyRunnableType;
1879
1880 auto p = MakeRefPtr<typename PromiseType::Private>(aCallerName);
1881 auto r = MakeRefPtr<ProxyRunnableType>(p, std::forward<Function>(aFunction));
1882 aTarget->Dispatch(r.forget());
1883 return p;
1884}
1885
1886#undef PROMISE_LOG
1887#undef PROMISE_ASSERT
1888#undef PROMISE_DEBUG
1889
1890} // namespace mozilla
1891
1892#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);
32
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 */