Bug Summary

File:root/firefox-clang/dom/media/MediaManager.cpp
Warning:line 2906, column 12
Value stored to 'rv' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_dom_media2.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 -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media -resource-dir /usr/lib/llvm-21/lib/clang/21 -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 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D HAVE_UINT64_T -D WEBRTC_MOZILLA_BUILD -D RTC_ENABLE_VP9 -D WEBRTC_POSIX -D WEBRTC_BUILD_LIBEVENT -D WEBRTC_LINUX -D WEBRTC_USE_PIPEWIRE -D WEBRTC_USE_X11 -D MOZILLA_INTERNAL_API -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 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libsoundtouch/src -I /root/firefox-clang/caps -I /root/firefox-clang/docshell/base -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/media/webrtc -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/xul -I /root/firefox-clang/media/libyuv/libyuv/include -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/toolkit/content/tests/browser -I /root/firefox-clang/dom/media/webrtc/common -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/third_party/libwebrtc -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/gfx/skia -I /root/firefox-clang/gfx/skia/skia -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/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -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-deprecated-this-capture -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-error=attributes -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 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-30-093548-1913035-1 -x c++ Unified_cpp_dom_media2.cpp
1/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2/* vim: set ts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "MediaManager.h"
8
9#include "AudioCaptureTrack.h"
10#include "AudioDeviceInfo.h"
11#include "AudioStreamTrack.h"
12#include "CubebDeviceEnumerator.h"
13#include "CubebInputStream.h"
14#include "MediaTimer.h"
15#include "MediaTrackConstraints.h"
16#include "MediaTrackGraph.h"
17#include "MediaTrackListener.h"
18#include "VideoStreamTrack.h"
19#include "Tracing.h"
20#include "VideoUtils.h"
21#include "mozilla/Base64.h"
22#include "mozilla/EventTargetCapability.h"
23#include "mozilla/MozPromise.h"
24#include "mozilla/NullPrincipal.h"
25#include "mozilla/PeerIdentity.h"
26#include "mozilla/PermissionDelegateHandler.h"
27#include "mozilla/Sprintf.h"
28#include "mozilla/StaticPrefs_media.h"
29#include "mozilla/glean/DomMediaWebrtcMetrics.h"
30#include "mozilla/Types.h"
31#include "mozilla/dom/BindingDeclarations.h"
32#include "mozilla/dom/Document.h"
33#include "mozilla/dom/Element.h"
34#include "mozilla/dom/FeaturePolicyUtils.h"
35#include "mozilla/dom/File.h"
36#include "mozilla/dom/GetUserMediaRequestBinding.h"
37#include "mozilla/dom/MediaDeviceInfo.h"
38#include "mozilla/dom/MediaDevices.h"
39#include "mozilla/dom/MediaDevicesBinding.h"
40#include "mozilla/dom/MediaStreamBinding.h"
41#include "mozilla/dom/MediaStreamTrackBinding.h"
42#include "mozilla/dom/Promise.h"
43#include "mozilla/dom/UserActivation.h"
44#include "mozilla/dom/WindowContext.h"
45#include "mozilla/dom/WindowGlobalChild.h"
46#include "mozilla/ipc/BackgroundChild.h"
47#include "mozilla/ipc/PBackgroundChild.h"
48#include "mozilla/media/CamerasTypes.h"
49#include "mozilla/media/MediaChild.h"
50#include "mozilla/media/MediaTaskUtils.h"
51#include "nsAppDirectoryServiceDefs.h"
52#include "nsArray.h"
53#include "nsContentUtils.h"
54#include "nsGlobalWindowInner.h"
55#include "nsHashPropertyBag.h"
56#include "nsIEventTarget.h"
57#include "nsIPermissionManager.h"
58#include "nsIUUIDGenerator.h"
59#include "nsJSUtils.h"
60#include "nsNetCID.h"
61#include "nsNetUtil.h"
62#include "nsProxyRelease.h"
63#include "nspr.h"
64#include "nss.h"
65#include "pk11pub.h"
66
67/* Using WebRTC backend on Desktops (Mac, Windows, Linux), otherwise default */
68#include "MediaEngineFake.h"
69#include "MediaEngineSource.h"
70#if defined(MOZ_WEBRTC1)
71# include "MediaEngineWebRTC.h"
72# include "MediaEngineWebRTCAudio.h"
73# include "browser_logging/WebRtcLog.h"
74# include "libwebrtcglue/WebrtcTaskQueueWrapper.h"
75# include "modules/audio_processing/include/audio_processing.h"
76#endif
77
78#if defined(XP_WIN)
79# include <objbase.h>
80#endif
81
82// A specialization of nsMainThreadPtrHolder for
83// mozilla::dom::CallbackObjectHolder. See documentation for
84// nsMainThreadPtrHolder in nsProxyRelease.h. This specialization lets us avoid
85// wrapping the CallbackObjectHolder into a separate refcounted object.
86template <class WebIDLCallbackT, class XPCOMCallbackT>
87class nsMainThreadPtrHolder<
88 mozilla::dom::CallbackObjectHolder<WebIDLCallbackT, XPCOMCallbackT>>
89 final {
90 typedef mozilla::dom::CallbackObjectHolder<WebIDLCallbackT, XPCOMCallbackT>
91 Holder;
92
93 public:
94 nsMainThreadPtrHolder(const char* aName, Holder&& aHolder)
95 : mHolder(std::move(aHolder))
96#ifndef RELEASE_OR_BETA
97 ,
98 mName(aName)
99#endif
100 {
101 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/MediaManager.cpp", 101); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 101); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
102 }
103
104 private:
105 // We can be released on any thread.
106 ~nsMainThreadPtrHolder() {
107 if (NS_IsMainThread()) {
108 mHolder.Reset();
109 } else if (mHolder.GetISupports()) {
110 nsCOMPtr<nsIEventTarget> target = do_GetMainThread();
111 MOZ_ASSERT(target)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(target)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(target))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("target", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 111); AnnotateMozCrashReason("MOZ_ASSERT" "(" "target" ")")
; do { MOZ_CrashSequence(__null, 111); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
112 NS_ProxyRelease(
113#ifdef RELEASE_OR_BETA
114 nullptr,
115#else
116 mName,
117#endif
118 target, mHolder.Forget());
119 }
120 }
121
122 public:
123 Holder* get() {
124 // Nobody should be touching the raw pointer off-main-thread.
125 if (MOZ_UNLIKELY(!NS_IsMainThread())(__builtin_expect(!!(!NS_IsMainThread()), 0))) {
126 NS_ERROR("Can't dereference nsMainThreadPtrHolder off main thread")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Can't dereference nsMainThreadPtrHolder off main thread"
, "Error", "/root/firefox-clang/dom/media/MediaManager.cpp", 126
); MOZ_PretendNoReturn(); } while (0)
;
127 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/root/firefox-clang/dom/media/MediaManager.cpp"
, 127); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence
(__null, 127); __attribute__((nomerge)) ::abort(); } while (false
); } while (false)
;
128 }
129 return &mHolder;
130 }
131
132 bool operator!() const { return !mHolder; }
133
134 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsMainThreadPtrHolder<Holder>)public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<nsMainThreadPtrHolder<Holder>
>, "Reference-counted class " "nsMainThreadPtrHolder<Holder>"
" 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/MediaManager.cpp"
, 134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 134
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("nsMainThreadPtrHolder<Holder>"), (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/dom/media/MediaManager.cpp"
, 134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 134
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("nsMainThreadPtrHolder<Holder>")); if (count ==
0) { delete (this); return 0; } return count; } using HasThreadSafeRefCnt
= std::true_type; protected: ::mozilla::ThreadSafeAutoRefCnt
mRefCnt; public:
135
136 private:
137 // Our holder.
138 Holder mHolder;
139
140#ifndef RELEASE_OR_BETA
141 const char* mName = nullptr;
142#endif
143
144 // Copy constructor and operator= not implemented. Once constructed, the
145 // holder is immutable.
146 Holder& operator=(const nsMainThreadPtrHolder& aOther) = delete;
147 nsMainThreadPtrHolder(const nsMainThreadPtrHolder& aOther) = delete;
148};
149
150namespace mozilla {
151
152LazyLogModule gMediaManagerLog("MediaManager");
153#define LOG(...) MOZ_LOG(gMediaManagerLog, LogLevel::Debug, (__VA_ARGS__))do { const ::mozilla::LogModule* moz_real_module = gMediaManagerLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, __VA_ARGS__); } } while (0)
154
155class GetUserMediaStreamTask;
156class LocalTrackSource;
157class SelectAudioOutputTask;
158
159using camera::CamerasAccessStatus;
160using dom::BFCacheStatus;
161using dom::CallerType;
162using dom::ConstrainDOMStringParameters;
163using dom::ConstrainDoubleRange;
164using dom::ConstrainLongRange;
165using dom::DisplayMediaStreamConstraints;
166using dom::Document;
167using dom::Element;
168using dom::FeaturePolicyUtils;
169using dom::File;
170using dom::GetUserMediaRequest;
171using dom::MediaDeviceKind;
172using dom::MediaDevices;
173using dom::MediaSourceEnum;
174using dom::MediaStreamConstraints;
175using dom::MediaStreamError;
176using dom::MediaStreamTrack;
177using dom::MediaStreamTrackSource;
178using dom::MediaTrackCapabilities;
179using dom::MediaTrackConstraints;
180using dom::MediaTrackConstraintSet;
181using dom::MediaTrackSettings;
182using dom::OwningBooleanOrMediaTrackConstraints;
183using dom::OwningStringOrStringSequence;
184using dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters;
185using dom::Promise;
186using dom::Sequence;
187using dom::UserActivation;
188using dom::VideoResizeModeEnum;
189using dom::WindowGlobalChild;
190using ConstDeviceSetPromise = MediaManager::ConstDeviceSetPromise;
191using DeviceSetPromise = MediaManager::DeviceSetPromise;
192using LocalDevicePromise = MediaManager::LocalDevicePromise;
193using LocalDeviceSetPromise = MediaManager::LocalDeviceSetPromise;
194using LocalMediaDeviceSetRefCnt = MediaManager::LocalMediaDeviceSetRefCnt;
195using MediaDeviceSetRefCnt = MediaManager::MediaDeviceSetRefCnt;
196using media::NewRunnableFrom;
197using media::NewTaskFrom;
198using media::Refcountable;
199
200// Whether main thread actions of MediaManager shutdown (except for clearing
201// of sSingleton) have completed.
202static bool sHasMainThreadShutdown;
203
204struct DeviceState {
205 DeviceState(RefPtr<LocalMediaDevice> aDevice,
206 RefPtr<LocalTrackSource> aTrackSource, bool aOffWhileDisabled)
207 : mOffWhileDisabled(aOffWhileDisabled),
208 mDevice(std::move(aDevice)),
209 mTrackSource(std::move(aTrackSource)) {
210 MOZ_ASSERT(mDevice)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDevice)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDevice))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDevice", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDevice" ")"
); do { MOZ_CrashSequence(__null, 210); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
211 MOZ_ASSERT(mTrackSource)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mTrackSource)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mTrackSource))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mTrackSource", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 211); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTrackSource"
")"); do { MOZ_CrashSequence(__null, 211); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
212 }
213
214 // true if we have stopped mDevice, this is a terminal state.
215 // MainThread only.
216 bool mStopped = false;
217
218 // true if mDevice is currently enabled.
219 // A device must be both enabled and unmuted to be turned on and capturing.
220 // MainThread only.
221 bool mDeviceEnabled = false;
222
223 // true if mDevice is currently muted.
224 // A device that is either muted or disabled is turned off and not capturing.
225 // MainThread only.
226 bool mDeviceMuted;
227
228 // true if the application has currently enabled mDevice.
229 // MainThread only.
230 bool mTrackEnabled = false;
231
232 // Time when the application last enabled mDevice.
233 // MainThread only.
234 TimeStamp mTrackEnabledTime;
235
236 // true if an operation to Start() or Stop() mDevice has been dispatched to
237 // the media thread and is not finished yet.
238 // MainThread only.
239 bool mOperationInProgress = false;
240
241 // true if we are allowed to turn off the underlying source while all tracks
242 // are disabled. Only affects disabling; always turns off on user-agent mute.
243 // MainThread only.
244 bool mOffWhileDisabled = false;
245
246 // Timer triggered by a MediaStreamTrackSource signaling that all tracks got
247 // disabled. When the timer fires we initiate Stop()ing mDevice.
248 // If set we allow dynamically stopping and starting mDevice.
249 // Any thread.
250 const RefPtr<MediaTimer<TimeStamp>> mDisableTimer =
251 new MediaTimer<TimeStamp>();
252
253 // The underlying device we keep state for. Always non-null.
254 // Threadsafe access, but see method declarations for individual constraints.
255 const RefPtr<LocalMediaDevice> mDevice;
256
257 // The MediaStreamTrackSource for any tracks (original and clones) originating
258 // from this device. Always non-null. Threadsafe access, but see method
259 // declarations for individual constraints.
260 const RefPtr<LocalTrackSource> mTrackSource;
261};
262
263/**
264 * This mimics the capture state from nsIMediaManagerService.
265 */
266enum class CaptureState : uint16_t {
267 Off = nsIMediaManagerService::STATE_NOCAPTURE,
268 Enabled = nsIMediaManagerService::STATE_CAPTURE_ENABLED,
269 Disabled = nsIMediaManagerService::STATE_CAPTURE_DISABLED,
270};
271
272static CaptureState CombineCaptureState(CaptureState aFirst,
273 CaptureState aSecond) {
274 if (aFirst == CaptureState::Enabled || aSecond == CaptureState::Enabled) {
275 return CaptureState::Enabled;
276 }
277 if (aFirst == CaptureState::Disabled || aSecond == CaptureState::Disabled) {
278 return CaptureState::Disabled;
279 }
280 MOZ_ASSERT(aFirst == CaptureState::Off)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFirst == CaptureState::Off)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFirst == CaptureState::Off)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aFirst == CaptureState::Off"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 280); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFirst == CaptureState::Off" ")"); do { MOZ_CrashSequence
(__null, 280); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
281 MOZ_ASSERT(aSecond == CaptureState::Off)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSecond == CaptureState::Off)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSecond == CaptureState::Off
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aSecond == CaptureState::Off", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 281); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSecond == CaptureState::Off"
")"); do { MOZ_CrashSequence(__null, 281); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
282 return CaptureState::Off;
283}
284
285static uint16_t FromCaptureState(CaptureState aState) {
286 MOZ_ASSERT(aState == CaptureState::Off || aState == CaptureState::Enabled ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aState == CaptureState::Off || aState == CaptureState
::Enabled || aState == CaptureState::Disabled)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aState == CaptureState::Off ||
aState == CaptureState::Enabled || aState == CaptureState::Disabled
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 287); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled"
")"); do { MOZ_CrashSequence(__null, 287); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
287 aState == CaptureState::Disabled)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aState == CaptureState::Off || aState == CaptureState
::Enabled || aState == CaptureState::Disabled)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aState == CaptureState::Off ||
aState == CaptureState::Enabled || aState == CaptureState::Disabled
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 287); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled"
")"); do { MOZ_CrashSequence(__null, 287); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
288 return static_cast<uint16_t>(aState);
289}
290
291void MediaManager::CallOnError(GetUserMediaErrorCallback& aCallback,
292 MediaStreamError& aError) {
293 aCallback.Call(aError);
294}
295
296void MediaManager::CallOnSuccess(GetUserMediaSuccessCallback& aCallback,
297 DOMMediaStream& aStream) {
298 aCallback.Call(aStream);
299}
300
301enum class PersistentPermissionState : uint32_t {
302 Unknown = nsIPermissionManager::UNKNOWN_ACTION,
303 Allow = nsIPermissionManager::ALLOW_ACTION,
304 Deny = nsIPermissionManager::DENY_ACTION,
305 Prompt = nsIPermissionManager::PROMPT_ACTION,
306};
307
308static PersistentPermissionState CheckPermission(
309 PersistentPermissionState aPermission) {
310 switch (aPermission) {
311 case PersistentPermissionState::Unknown:
312 case PersistentPermissionState::Allow:
313 case PersistentPermissionState::Deny:
314 case PersistentPermissionState::Prompt:
315 return aPermission;
316 }
317 MOZ_CRASH("Unexpected permission value")do { do { } while (false); MOZ_ReportCrash("" "Unexpected permission value"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 317); AnnotateMozCrashReason
("MOZ_CRASH(" "Unexpected permission value" ")"); do { MOZ_CrashSequence
(__null, 317); __attribute__((nomerge)) ::abort(); } while (false
); } while (false)
;
318}
319
320struct WindowPersistentPermissionState {
321 PersistentPermissionState mCameraPermission;
322 PersistentPermissionState mMicrophonePermission;
323};
324
325static Result<WindowPersistentPermissionState, nsresult>
326GetPersistentPermissions(uint64_t aWindowId) {
327 auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowId);
328 if (NS_WARN_IF(!window)NS_warn_if_impl(!window, "!window", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 328)
|| NS_WARN_IF(!window->GetPrincipal())NS_warn_if_impl(!window->GetPrincipal(), "!window->GetPrincipal()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 328)
) {
329 return Err(NS_ERROR_INVALID_ARG);
330 }
331
332 Document* doc = window->GetExtantDoc();
333 if (NS_WARN_IF(!doc)NS_warn_if_impl(!doc, "!doc", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 333)
) {
334 return Err(NS_ERROR_INVALID_ARG);
335 }
336
337 nsIPrincipal* principal = window->GetPrincipal();
338 if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 338)
) {
339 return Err(NS_ERROR_INVALID_ARG);
340 }
341
342 nsresult rv;
343 RefPtr<PermissionDelegateHandler> permDelegate =
344 doc->GetPermissionDelegateHandler();
345 if (NS_WARN_IF(!permDelegate)NS_warn_if_impl(!permDelegate, "!permDelegate", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 345)
) {
346 return Err(NS_ERROR_INVALID_ARG);
347 }
348
349 uint32_t audio = nsIPermissionManager::UNKNOWN_ACTION;
350 uint32_t video = nsIPermissionManager::UNKNOWN_ACTION;
351 {
352 rv = permDelegate->GetPermission("microphone"_ns, &audio, true);
353 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 353)
) {
354 return Err(rv);
355 }
356 rv = permDelegate->GetPermission("camera"_ns, &video, true);
357 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 357)
) {
358 return Err(rv);
359 }
360 }
361
362 return WindowPersistentPermissionState{
363 CheckPermission(static_cast<PersistentPermissionState>(video)),
364 CheckPermission(static_cast<PersistentPermissionState>(audio))};
365}
366
367/**
368 * DeviceListener has threadsafe refcounting for use across the main, media and
369 * MTG threads. But it has a non-threadsafe SupportsWeakPtr for WeakPtr usage
370 * only from main thread, to ensure that garbage- and cycle-collected objects
371 * don't hold a reference to it during late shutdown.
372 */
373class DeviceListener : public SupportsWeakPtr {
374 public:
375 typedef MozPromise<bool /* aIgnored */, RefPtr<MediaMgrError>, false>
376 DeviceListenerPromise;
377
378 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<DeviceListener>, "Reference-counted class "
"DeviceListener" " 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/MediaManager.cpp"
, 379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 379
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("DeviceListener"), (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/dom/media/MediaManager.cpp"
, 379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 379
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("DeviceListener")); if (count == 0) { ::mozilla::detail
::ProxyDeleteVoid( "ProxyDelete " "DeviceListener", ::mozilla
::GetMainThreadSerialEventTarget(), this, [](void* self) { delete
static_cast<DeviceListener*>(self); }); return 0; } return
count; } using HasThreadSafeRefCnt = std::true_type; protected
: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public:
379 DeviceListener)public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<DeviceListener>, "Reference-counted class "
"DeviceListener" " 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/MediaManager.cpp"
, 379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 379
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("DeviceListener"), (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/dom/media/MediaManager.cpp"
, 379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 379
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("DeviceListener")); if (count == 0) { ::mozilla::detail
::ProxyDeleteVoid( "ProxyDelete " "DeviceListener", ::mozilla
::GetMainThreadSerialEventTarget(), this, [](void* self) { delete
static_cast<DeviceListener*>(self); }); return 0; } return
count; } using HasThreadSafeRefCnt = std::true_type; protected
: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public:
380
381 DeviceListener();
382
383 /**
384 * Registers this device listener as belonging to the given window listener.
385 * Stop() must be called on registered DeviceListeners before destruction.
386 */
387 void Register(GetUserMediaWindowListener* aListener);
388
389 /**
390 * Marks this listener as active and creates the internal device state.
391 */
392 void Activate(RefPtr<LocalMediaDevice> aDevice,
393 RefPtr<LocalTrackSource> aTrackSource, bool aStartMuted);
394
395 /**
396 * Posts a task to initialize and start the associated device.
397 */
398 RefPtr<DeviceListenerPromise> InitializeAsync();
399
400 /**
401 * Posts a task to stop the device associated with this DeviceListener and
402 * notifies the associated window listener that a track was stopped.
403 *
404 * This will also clean up the weak reference to the associated window
405 * listener, and tell the window listener to remove its hard reference to this
406 * DeviceListener, so any caller will need to keep its own hard ref.
407 */
408 void Stop();
409
410 /**
411 * Gets the main thread MediaTrackSettings from the MediaEngineSource
412 * associated with aTrack.
413 */
414 void GetSettings(MediaTrackSettings& aOutSettings) const;
415
416 /**
417 * Gets the main thread MediaTrackCapabilities from the MediaEngineSource
418 * associated with aTrack.
419 */
420 void GetCapabilities(MediaTrackCapabilities& aOutCapabilities) const;
421
422 /**
423 * Posts a task to set the enabled state of the device associated with this
424 * DeviceListener to aEnabled and notifies the associated window listener that
425 * a track's state has changed.
426 *
427 * Turning the hardware off while the device is disabled is supported for:
428 * - Camera (enabled by default, controlled by pref
429 * "media.getusermedia.camera.off_while_disabled.enabled")
430 * - Microphone (disabled by default, controlled by pref
431 * "media.getusermedia.microphone.off_while_disabled.enabled")
432 * Screen-, app-, or windowsharing is not supported at this time.
433 *
434 * The behavior is also different between disabling and enabling a device.
435 * While enabling is immediate, disabling only happens after a delay.
436 * This is now defaulting to 3 seconds but can be overriden by prefs:
437 * - "media.getusermedia.camera.off_while_disabled.delay_ms" and
438 * - "media.getusermedia.microphone.off_while_disabled.delay_ms".
439 *
440 * The delay is in place to prevent misuse by malicious sites. If a track is
441 * re-enabled before the delay has passed, the device will not be touched
442 * until another disable followed by the full delay happens.
443 */
444 void SetDeviceEnabled(bool aEnabled);
445
446 /**
447 * Posts a task to set the muted state of the device associated with this
448 * DeviceListener to aMuted and notifies the associated window listener that a
449 * track's state has changed.
450 *
451 * Turning the hardware off while the device is muted is supported for:
452 * - Camera (enabled by default, controlled by pref
453 * "media.getusermedia.camera.off_while_disabled.enabled")
454 * - Microphone (disabled by default, controlled by pref
455 * "media.getusermedia.microphone.off_while_disabled.enabled")
456 * Screen-, app-, or windowsharing is not supported at this time.
457 */
458 void SetDeviceMuted(bool aMuted);
459
460 /**
461 * Mutes or unmutes the associated video device if it is a camera.
462 */
463 void MuteOrUnmuteCamera(bool aMute);
464 void MuteOrUnmuteMicrophone(bool aMute);
465
466 LocalMediaDevice* GetDevice() const {
467 return mDeviceState ? mDeviceState->mDevice.get() : nullptr;
468 }
469
470 bool Activated() const { return static_cast<bool>(mDeviceState); }
471
472 bool Stopped() const { return mStopped; }
473
474 bool CapturingVideo() const;
475
476 bool CapturingAudio() const;
477
478 CaptureState CapturingSource(MediaSourceEnum aSource) const;
479
480 RefPtr<DeviceListenerPromise> ApplyConstraints(
481 const MediaTrackConstraints& aConstraints, CallerType aCallerType);
482
483 PrincipalHandle GetPrincipalHandle() const;
484
485 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
486 size_t amount = aMallocSizeOf(this);
487 // Assume mPrincipalHandle refers to a principal owned elsewhere.
488 // DeviceState does not have support for memory accounting.
489 return amount;
490 }
491
492 private:
493 virtual ~DeviceListener() {
494 MOZ_ASSERT(mStopped)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mStopped)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mStopped", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ")"
); do { MOZ_CrashSequence(__null, 494); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
495 MOZ_ASSERT(!mWindowListener)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mWindowListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mWindowListener))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mWindowListener"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 495); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mWindowListener" ")"); do { MOZ_CrashSequence
(__null, 495); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
496 }
497
498 using DeviceOperationPromise =
499 MozPromise<nsresult, bool, /* IsExclusive = */ true>;
500
501 /**
502 * Posts a task to start or stop the device associated with aTrack, based on
503 * a passed-in boolean. Private method used by SetDeviceEnabled and
504 * SetDeviceMuted.
505 */
506 RefPtr<DeviceOperationPromise> UpdateDevice(bool aOn);
507
508 // true after this listener has had all devices stopped. MainThread only.
509 bool mStopped;
510
511 // never ever indirect off this; just for assertions
512 PRThread* mMainThreadCheck;
513
514 // Set in Register() on main thread, then read from any thread.
515 PrincipalHandle mPrincipalHandle;
516
517 // Weak pointer to the window listener that owns us. MainThread only.
518 GetUserMediaWindowListener* mWindowListener;
519
520 // Accessed from MediaTrackGraph thread, MediaManager thread, and MainThread
521 // No locking needed as it's set on Activate() and never assigned to again.
522 UniquePtr<DeviceState> mDeviceState;
523
524 MediaEventListener mCaptureEndedListener;
525};
526
527/**
528 * This class represents a WindowID and handles all MediaTrackListeners
529 * (here subclassed as DeviceListeners) used to feed GetUserMedia tracks.
530 * It proxies feedback from them into messages for browser chrome.
531 * The DeviceListeners are used to Start() and Stop() the underlying
532 * MediaEngineSource when MediaStreams are assigned and deassigned in content.
533 */
534class GetUserMediaWindowListener {
535 friend MediaManager;
536
537 public:
538 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GetUserMediaWindowListener)public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<GetUserMediaWindowListener>, "Reference-counted class "
"GetUserMediaWindowListener" " 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/MediaManager.cpp"
, 538); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 538
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("GetUserMediaWindowListener"), (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/dom/media/MediaManager.cpp"
, 538); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 538
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("GetUserMediaWindowListener")); if (count == 0) { delete
(this); return 0; } return count; } using HasThreadSafeRefCnt
= std::true_type; protected: ::mozilla::ThreadSafeAutoRefCnt
mRefCnt; public:
539
540 // Create in an inactive state
541 GetUserMediaWindowListener(uint64_t aWindowID,
542 const PrincipalHandle& aPrincipalHandle)
543 : mWindowID(aWindowID),
544 mPrincipalHandle(aPrincipalHandle),
545 mChromeNotificationTaskPosted(false) {}
546
547 /**
548 * Registers an inactive gUM device listener for this WindowListener.
549 */
550 void Register(RefPtr<DeviceListener> aListener) {
551 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/MediaManager.cpp", 551); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 551); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
552 MOZ_ASSERT(aListener)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aListener", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 552); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aListener" ")"
); do { MOZ_CrashSequence(__null, 552); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
553 MOZ_ASSERT(!aListener->Activated())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aListener->Activated())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aListener->Activated()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aListener->Activated()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 553); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aListener->Activated()" ")"); do { MOZ_CrashSequence
(__null, 553); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
554 MOZ_ASSERT(!mInactiveListeners.Contains(aListener), "Already registered")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mInactiveListeners.Contains(aListener))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)"
" (" "Already registered" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)"
") (" "Already registered" ")"); do { MOZ_CrashSequence(__null
, 554); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
555 MOZ_ASSERT(!mActiveListeners.Contains(aListener), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mActiveListeners.Contains(aListener))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!mActiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)"
" (" "Already activated" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)"
") (" "Already activated" ")"); do { MOZ_CrashSequence(__null
, 555); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
556
557 aListener->Register(this);
558 mInactiveListeners.AppendElement(std::move(aListener));
559 }
560
561 /**
562 * Activates an already registered and inactive gUM device listener for this
563 * WindowListener.
564 */
565 void Activate(RefPtr<DeviceListener> aListener,
566 RefPtr<LocalMediaDevice> aDevice,
567 RefPtr<LocalTrackSource> aTrackSource) {
568 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/MediaManager.cpp", 568); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 568); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
569 MOZ_ASSERT(aListener)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aListener", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aListener" ")"
); do { MOZ_CrashSequence(__null, 569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
570 MOZ_ASSERT(!aListener->Activated())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aListener->Activated())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aListener->Activated()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aListener->Activated()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 570); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aListener->Activated()" ")"); do { MOZ_CrashSequence
(__null, 570); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
571 MOZ_ASSERT(mInactiveListeners.Contains(aListener),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInactiveListeners.Contains(aListener))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mInactiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mInactiveListeners.Contains(aListener)"
" (" "Must be registered to activate" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Contains(aListener)"
") (" "Must be registered to activate" ")"); do { MOZ_CrashSequence
(__null, 572); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
572 "Must be registered to activate")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInactiveListeners.Contains(aListener))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mInactiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mInactiveListeners.Contains(aListener)"
" (" "Must be registered to activate" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Contains(aListener)"
") (" "Must be registered to activate" ")"); do { MOZ_CrashSequence
(__null, 572); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
573 MOZ_ASSERT(!mActiveListeners.Contains(aListener), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mActiveListeners.Contains(aListener))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!mActiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)"
" (" "Already activated" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 573); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)"
") (" "Already activated" ")"); do { MOZ_CrashSequence(__null
, 573); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
574
575 bool muted = false;
576 if (aDevice->Kind() == MediaDeviceKind::Videoinput) {
577 muted = mCamerasAreMuted;
578 } else if (aDevice->Kind() == MediaDeviceKind::Audioinput) {
579 muted = mMicrophonesAreMuted;
580 } else {
581 MOZ_CRASH("Unexpected device kind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected device kind"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 581); AnnotateMozCrashReason
("MOZ_CRASH(" "Unexpected device kind" ")"); do { MOZ_CrashSequence
(__null, 581); __attribute__((nomerge)) ::abort(); } while (false
); } while (false)
;
582 }
583
584 mInactiveListeners.RemoveElement(aListener);
585 aListener->Activate(std::move(aDevice), std::move(aTrackSource), muted);
586 mActiveListeners.AppendElement(std::move(aListener));
587 }
588
589 /**
590 * Removes all DeviceListeners from this window listener.
591 * Removes this window listener from the list of active windows, so callers
592 * need to make sure to hold a strong reference.
593 */
594 void RemoveAll() {
595 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/MediaManager.cpp", 595); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 595); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
596
597 for (auto& l : mInactiveListeners.Clone()) {
598 Remove(l);
599 }
600 for (auto& l : mActiveListeners.Clone()) {
601 Remove(l);
602 }
603 MOZ_ASSERT(mInactiveListeners.Length() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInactiveListeners.Length() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInactiveListeners.Length() ==
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mInactiveListeners.Length() == 0", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Length() == 0"
")"); do { MOZ_CrashSequence(__null, 603); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
604 MOZ_ASSERT(mActiveListeners.Length() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mActiveListeners.Length() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mActiveListeners.Length() ==
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mActiveListeners.Length() == 0", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActiveListeners.Length() == 0"
")"); do { MOZ_CrashSequence(__null, 604); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
605
606 MediaManager* mgr = MediaManager::GetIfExists();
607 if (!mgr) {
608 MOZ_ASSERT(false, "MediaManager should stay until everything is removed")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MediaManager should stay until everything is removed"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 608);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MediaManager should stay until everything is removed"
")"); do { MOZ_CrashSequence(__null, 608); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
609 return;
610 }
611 GetUserMediaWindowListener* windowListener =
612 mgr->GetWindowListener(mWindowID);
613
614 if (!windowListener) {
615 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
616 auto* globalWindow = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID);
617 if (globalWindow) {
618 auto req = MakeRefPtr<GetUserMediaRequest>(
619 globalWindow, VoidString(), VoidString(),
620 UserActivation::IsHandlingUserInput());
621 obs->NotifyWhenScriptSafe(req, "recording-device-stopped", nullptr);
622 }
623 return;
624 }
625
626 MOZ_ASSERT(windowListener == this,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(windowListener == this)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(windowListener == this))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener == this"
" (" "There should only be one window listener per window ID"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 627);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener == this"
") (" "There should only be one window listener per window ID"
")"); do { MOZ_CrashSequence(__null, 627); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
627 "There should only be one window listener per window ID")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(windowListener == this)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(windowListener == this))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener == this"
" (" "There should only be one window listener per window ID"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 627);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener == this"
") (" "There should only be one window listener per window ID"
")"); do { MOZ_CrashSequence(__null, 627); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
628
629 LOG("GUMWindowListener %p removing windowID %" PRIu64"l" "u", this, mWindowID);
630 mgr->RemoveWindowID(mWindowID);
631 }
632
633 /**
634 * Removes a listener from our lists. Safe to call without holding a hard
635 * reference. That said, you'll still want to iterate on a copy of said lists,
636 * if you end up calling this method (or methods that may call this method) in
637 * the loop, to avoid inadvertently skipping members.
638 *
639 * For use only from GetUserMediaWindowListener and DeviceListener.
640 */
641 bool Remove(RefPtr<DeviceListener> aListener) {
642 // We refcount aListener on entry since we're going to proxy-release it
643 // below to prevent the refcount going to zero on callers who might be
644 // inside the listener, but operating without a hard reference to self.
645 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/MediaManager.cpp", 645); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 645); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
646
647 if (!mInactiveListeners.RemoveElement(aListener) &&
648 !mActiveListeners.RemoveElement(aListener)) {
649 return false;
650 }
651 MOZ_ASSERT(!mInactiveListeners.Contains(aListener),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mInactiveListeners.Contains(aListener))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)"
" (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 653);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)"
") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")"); do { MOZ_CrashSequence(__null, 653); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
652 "A DeviceListener should only be once in one of "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mInactiveListeners.Contains(aListener))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)"
" (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 653);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)"
") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")"); do { MOZ_CrashSequence(__null, 653); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
653 "mInactiveListeners and mActiveListeners")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mInactiveListeners.Contains(aListener))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)"
" (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 653);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)"
") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")"); do { MOZ_CrashSequence(__null, 653); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
654 MOZ_ASSERT(!mActiveListeners.Contains(aListener),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mActiveListeners.Contains(aListener))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!mActiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)"
" (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 656);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)"
") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")"); do { MOZ_CrashSequence(__null, 656); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
655 "A DeviceListener should only be once in one of "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mActiveListeners.Contains(aListener))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!mActiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)"
" (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 656);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)"
") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")"); do { MOZ_CrashSequence(__null, 656); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
656 "mInactiveListeners and mActiveListeners")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mActiveListeners.Contains(aListener))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!mActiveListeners.Contains(aListener)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)"
" (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 656);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)"
") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners"
")"); do { MOZ_CrashSequence(__null, 656); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
657
658 LOG("GUMWindowListener %p stopping DeviceListener %p.", this,
659 aListener.get());
660 aListener->Stop();
661
662 if (LocalMediaDevice* removedDevice = aListener->GetDevice()) {
663 bool revokePermission = true;
664 nsString removedRawId;
665 nsString removedSourceType;
666 removedDevice->GetRawId(removedRawId);
667 removedDevice->GetMediaSource(removedSourceType);
668
669 for (const auto& l : mActiveListeners) {
670 if (LocalMediaDevice* device = l->GetDevice()) {
671 nsString rawId;
672 device->GetRawId(rawId);
673 if (removedRawId.Equals(rawId)) {
674 revokePermission = false;
675 break;
676 }
677 }
678 }
679
680 if (revokePermission) {
681 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
682 auto* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID);
683 auto req = MakeRefPtr<GetUserMediaRequest>(
684 window, removedRawId, removedSourceType,
685 UserActivation::IsHandlingUserInput());
686 obs->NotifyWhenScriptSafe(req, "recording-device-stopped", nullptr);
687 }
688 }
689
690 if (mInactiveListeners.Length() == 0 && mActiveListeners.Length() == 0) {
691 LOG("GUMWindowListener %p Removed last DeviceListener. Cleaning up.",
692 this);
693 RemoveAll();
694 }
695
696 nsCOMPtr<nsIEventTarget> mainTarget = do_GetMainThread();
697 // To allow being invoked by callers not holding a strong reference to self,
698 // hold the listener alive until the stack has unwound, by always
699 // dispatching a runnable (aAlwaysProxy = true)
700 NS_ProxyRelease(__func__, mainTarget, aListener.forget(), true);
701 return true;
702 }
703
704 /**
705 * Stops all screen/window/audioCapture sharing, but not camera or microphone.
706 */
707 void StopSharing();
708
709 void StopRawID(const nsString& removedDeviceID);
710
711 void MuteOrUnmuteCameras(bool aMute);
712 void MuteOrUnmuteMicrophones(bool aMute);
713
714 /**
715 * Called by one of our DeviceListeners when one of its tracks has changed so
716 * that chrome state is affected.
717 * Schedules an event for the next stable state to update chrome.
718 */
719 void ChromeAffectingStateChanged();
720
721 /**
722 * Called in stable state to send a notification to update chrome.
723 */
724 void NotifyChrome();
725
726 bool CapturingVideo() const {
727 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/MediaManager.cpp", 727); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 727); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
728 for (auto& l : mActiveListeners) {
729 if (l->CapturingVideo()) {
730 return true;
731 }
732 }
733 return false;
734 }
735
736 bool CapturingAudio() const {
737 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/MediaManager.cpp", 737); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 737); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
738 for (auto& l : mActiveListeners) {
739 if (l->CapturingAudio()) {
740 return true;
741 }
742 }
743 return false;
744 }
745
746 CaptureState CapturingSource(MediaSourceEnum aSource) const {
747 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/MediaManager.cpp", 747); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 747); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
748 CaptureState result = CaptureState::Off;
749 for (auto& l : mActiveListeners) {
750 result = CombineCaptureState(result, l->CapturingSource(aSource));
751 }
752 return result;
753 }
754
755 RefPtr<LocalMediaDeviceSetRefCnt> GetDevices() {
756 RefPtr devices = new LocalMediaDeviceSetRefCnt();
757 for (auto& l : mActiveListeners) {
758 devices->AppendElement(l->GetDevice());
759 }
760 return devices;
761 }
762
763 uint64_t WindowID() const { return mWindowID; }
764
765 PrincipalHandle GetPrincipalHandle() const { return mPrincipalHandle; }
766
767 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
768 size_t amount = aMallocSizeOf(this);
769 // Assume mPrincipalHandle refers to a principal owned elsewhere.
770 amount += mInactiveListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
771 for (const RefPtr<DeviceListener>& listener : mInactiveListeners) {
772 amount += listener->SizeOfIncludingThis(aMallocSizeOf);
773 }
774 amount += mActiveListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
775 for (const RefPtr<DeviceListener>& listener : mActiveListeners) {
776 amount += listener->SizeOfIncludingThis(aMallocSizeOf);
777 }
778 return amount;
779 }
780
781 private:
782 ~GetUserMediaWindowListener() {
783 MOZ_ASSERT(mInactiveListeners.Length() == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInactiveListeners.Length() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInactiveListeners.Length() ==
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mInactiveListeners.Length() == 0" " (" "Inactive listeners should already be removed"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 784);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Length() == 0"
") (" "Inactive listeners should already be removed" ")"); do
{ MOZ_CrashSequence(__null, 784); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
784 "Inactive listeners should already be removed")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInactiveListeners.Length() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInactiveListeners.Length() ==
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mInactiveListeners.Length() == 0" " (" "Inactive listeners should already be removed"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 784);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Length() == 0"
") (" "Inactive listeners should already be removed" ")"); do
{ MOZ_CrashSequence(__null, 784); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
785 MOZ_ASSERT(mActiveListeners.Length() == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mActiveListeners.Length() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mActiveListeners.Length() ==
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mActiveListeners.Length() == 0" " (" "Active listeners should already be removed"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 786);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActiveListeners.Length() == 0"
") (" "Active listeners should already be removed" ")"); do {
MOZ_CrashSequence(__null, 786); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
786 "Active listeners should already be removed")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mActiveListeners.Length() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mActiveListeners.Length() ==
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mActiveListeners.Length() == 0" " (" "Active listeners should already be removed"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 786);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActiveListeners.Length() == 0"
") (" "Active listeners should already be removed" ")"); do {
MOZ_CrashSequence(__null, 786); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
787 }
788
789 uint64_t mWindowID;
790 const PrincipalHandle mPrincipalHandle;
791
792 // true if we have scheduled a task to notify chrome in the next stable state.
793 // The task will reset this to false. MainThread only.
794 bool mChromeNotificationTaskPosted;
795
796 nsTArray<RefPtr<DeviceListener>> mInactiveListeners;
797 nsTArray<RefPtr<DeviceListener>> mActiveListeners;
798
799 // Whether camera and microphone access in this window are currently
800 // User Agent (UA) muted. When true, new and cloned tracks must start
801 // out muted, to avoid JS circumventing UA mute. Per-camera and
802 // per-microphone UA muting is not supported.
803 bool mCamerasAreMuted = false;
804 bool mMicrophonesAreMuted = false;
805};
806
807class LocalTrackSource : public MediaStreamTrackSource {
808 public:
809 LocalTrackSource(nsIPrincipal* aPrincipal, const nsString& aLabel,
810 const RefPtr<DeviceListener>& aListener,
811 MediaSourceEnum aSource, MediaTrack* aTrack,
812 RefPtr<PeerIdentity> aPeerIdentity,
813 TrackingId aTrackingId = TrackingId())
814 : MediaStreamTrackSource(aPrincipal, aLabel, std::move(aTrackingId)),
815 mSource(aSource),
816 mTrack(aTrack),
817 mPeerIdentity(std::move(aPeerIdentity)),
818 mListener(aListener.get()) {}
819
820 MediaSourceEnum GetMediaSource() const override { return mSource; }
821
822 const PeerIdentity* GetPeerIdentity() const override { return mPeerIdentity; }
823
824 RefPtr<MediaStreamTrackSource::ApplyConstraintsPromise> ApplyConstraints(
825 const MediaTrackConstraints& aConstraints,
826 CallerType aCallerType) override {
827 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/MediaManager.cpp", 827); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 827); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
828 if (sHasMainThreadShutdown || !mListener) {
829 // Track has been stopped, or we are in shutdown. In either case
830 // there's no observable outcome, so pretend we succeeded.
831 return MediaStreamTrackSource::ApplyConstraintsPromise::CreateAndResolve(
832 false, __func__);
833 }
834 auto p = mListener->ApplyConstraints(aConstraints, aCallerType);
835 p->Then(
836 GetCurrentSerialEventTarget(), __func__,
837 [aConstraints, this, self = RefPtr(this)] {
838 ConstraintsChanged(aConstraints);
839 },
840 [] {});
841 return p;
842 }
843
844 void GetSettings(MediaTrackSettings& aOutSettings) override {
845 if (mListener) {
846 mListener->GetSettings(aOutSettings);
847 }
848 }
849
850 void GetCapabilities(MediaTrackCapabilities& aOutCapabilities) override {
851 if (mListener) {
852 mListener->GetCapabilities(aOutCapabilities);
853 }
854 }
855
856 void Stop() override {
857 if (mListener) {
858 mListener->Stop();
859 mListener = nullptr;
860 }
861 if (!mTrack->IsDestroyed()) {
862 mTrack->Destroy();
863 }
864 }
865
866 void Disable() override {
867 if (mListener) {
868 mListener->SetDeviceEnabled(false);
869 }
870 }
871
872 void Enable() override {
873 if (mListener) {
874 mListener->SetDeviceEnabled(true);
875 }
876 }
877
878 void Mute() {
879 MutedChanged(true);
880 mTrack->SetDisabledTrackMode(DisabledTrackMode::SILENCE_BLACK);
881 }
882
883 void Unmute() {
884 MutedChanged(false);
885 mTrack->SetDisabledTrackMode(DisabledTrackMode::ENABLED);
886 }
887
888 const MediaSourceEnum mSource;
889 const RefPtr<MediaTrack> mTrack;
890 const RefPtr<const PeerIdentity> mPeerIdentity;
891
892 protected:
893 ~LocalTrackSource() {
894 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/MediaManager.cpp", 894); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 894); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
895 MOZ_ASSERT(mTrack->IsDestroyed())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mTrack->IsDestroyed())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mTrack->IsDestroyed()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mTrack->IsDestroyed()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 895); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mTrack->IsDestroyed()" ")"); do { MOZ_CrashSequence
(__null, 895); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
896 }
897
898 // This is a weak pointer to avoid having the DeviceListener (which may
899 // have references to threads and threadpools) kept alive by DOM-objects
900 // that may have ref-cycles and thus are released very late during
901 // shutdown, even after xpcom-shutdown-threads. See bug 1351655 for what
902 // can happen.
903 WeakPtr<DeviceListener> mListener;
904};
905
906class AudioCaptureTrackSource : public LocalTrackSource {
907 public:
908 AudioCaptureTrackSource(nsIPrincipal* aPrincipal, nsPIDOMWindowInner* aWindow,
909 const nsString& aLabel,
910 AudioCaptureTrack* aAudioCaptureTrack,
911 RefPtr<PeerIdentity> aPeerIdentity)
912 : LocalTrackSource(aPrincipal, aLabel, nullptr,
913 MediaSourceEnum::AudioCapture, aAudioCaptureTrack,
914 std::move(aPeerIdentity)),
915 mWindow(aWindow),
916 mAudioCaptureTrack(aAudioCaptureTrack) {
917 mAudioCaptureTrack->Start();
918 mAudioCaptureTrack->Graph()->RegisterCaptureTrackForWindow(
919 mWindow->WindowID(), mAudioCaptureTrack);
920 mWindow->SetAudioCapture(true);
921 }
922
923 void Stop() override {
924 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/MediaManager.cpp", 924); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 924); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
925 if (!mAudioCaptureTrack->IsDestroyed()) {
926 MOZ_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mWindow", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 926); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")"
); do { MOZ_CrashSequence(__null, 926); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
927 mWindow->SetAudioCapture(false);
928 mAudioCaptureTrack->Graph()->UnregisterCaptureTrackForWindow(
929 mWindow->WindowID());
930 mWindow = nullptr;
931 }
932 // LocalTrackSource destroys the track.
933 LocalTrackSource::Stop();
934 MOZ_ASSERT(mAudioCaptureTrack->IsDestroyed())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAudioCaptureTrack->IsDestroyed())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAudioCaptureTrack->IsDestroyed
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mAudioCaptureTrack->IsDestroyed()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudioCaptureTrack->IsDestroyed()"
")"); do { MOZ_CrashSequence(__null, 934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
935 }
936
937 ProcessedMediaTrack* InputTrack() const { return mAudioCaptureTrack.get(); }
938
939 protected:
940 ~AudioCaptureTrackSource() {
941 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/MediaManager.cpp", 941); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 941); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
942 MOZ_ASSERT(mAudioCaptureTrack->IsDestroyed())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAudioCaptureTrack->IsDestroyed())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAudioCaptureTrack->IsDestroyed
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mAudioCaptureTrack->IsDestroyed()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 942); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudioCaptureTrack->IsDestroyed()"
")"); do { MOZ_CrashSequence(__null, 942); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
943 }
944
945 RefPtr<nsPIDOMWindowInner> mWindow;
946 const RefPtr<AudioCaptureTrack> mAudioCaptureTrack;
947};
948
949/**
950 * nsIMediaDevice implementation.
951 */
952NS_IMPL_ISUPPORTS(LocalMediaDevice, nsIMediaDevice)MozExternalRefCountType LocalMediaDevice::AddRef(void) { static_assert
(!std::is_destructible_v<LocalMediaDevice>, "Reference-counted class "
"LocalMediaDevice" " 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/MediaManager.cpp"
, 952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 952
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("LocalMediaDevice" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("LocalMediaDevice" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"LocalMediaDevice\" != nullptr" " (" "Must specify a name" ")"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 952); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "\"LocalMediaDevice\" != nullptr" ") (" "Must specify a name"
")"); do { MOZ_CrashSequence(__null, 952); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (!mRefCnt
.isThreadSafe) _mOwningThread.AssertOwnership("LocalMediaDevice"
" not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef
((this), (count), ("LocalMediaDevice"), (uint32_t)(sizeof(*this
))); return count; } MozExternalRefCountType LocalMediaDevice
::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/MediaManager.cpp"
, 952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 952
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("LocalMediaDevice" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("LocalMediaDevice" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"LocalMediaDevice\" != nullptr" " (" "Must specify a name" ")"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 952); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "\"LocalMediaDevice\" != nullptr" ") (" "Must specify a name"
")"); do { MOZ_CrashSequence(__null, 952); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (!mRefCnt
.isThreadSafe) _mOwningThread.AssertOwnership("LocalMediaDevice"
" not thread-safe"); const char* const nametmp = "LocalMediaDevice"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult LocalMediaDevice::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/MediaManager.cpp"
, 952); 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<LocalMediaDevice, nsIMediaDevice>, int32_t
( reinterpret_cast<char*>(static_cast<nsIMediaDevice
*>((LocalMediaDevice*)0x1000)) - reinterpret_cast<char*
>((LocalMediaDevice*)0x1000))}, {&mozilla::detail::kImplementedIID
<LocalMediaDevice, nsISupports>, int32_t(reinterpret_cast
<char*>(static_cast<nsISupports*>( static_cast<
nsIMediaDevice*>((LocalMediaDevice*)0x1000))) - reinterpret_cast
<char*>((LocalMediaDevice*)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; }
953
954MediaDevice::MediaDevice(MediaEngine* aEngine, MediaSourceEnum aMediaSource,
955 const nsString& aRawName, const nsString& aRawID,
956 const nsString& aRawGroupID, IsScary aIsScary,
957 const OsPromptable canRequestOsLevelPrompt,
958 const IsPlaceholder aIsPlaceholder)
959 : mEngine(aEngine),
960 mAudioDeviceInfo(nullptr),
961 mMediaSource(aMediaSource),
962 mKind(MediaEngineSource::IsVideo(aMediaSource)
963 ? MediaDeviceKind::Videoinput
964 : MediaDeviceKind::Audioinput),
965 mScary(aIsScary == IsScary::Yes),
966 mCanRequestOsLevelPrompt(canRequestOsLevelPrompt == OsPromptable::Yes),
967 mIsFake(mEngine->IsFake()),
968 mIsPlaceholder(aIsPlaceholder == IsPlaceholder::Yes),
969 mType(NS_ConvertASCIItoUTF16(dom::GetEnumString(mKind))),
970 mRawID(aRawID),
971 mRawGroupID(aRawGroupID),
972 mRawName(aRawName) {
973 MOZ_ASSERT(mEngine)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mEngine)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mEngine))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mEngine", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mEngine" ")"
); do { MOZ_CrashSequence(__null, 973); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
974}
975
976MediaDevice::MediaDevice(MediaEngine* aEngine,
977 const RefPtr<AudioDeviceInfo>& aAudioDeviceInfo,
978 const nsString& aRawID)
979 : mEngine(aEngine),
980 mAudioDeviceInfo(aAudioDeviceInfo),
981 mMediaSource(mAudioDeviceInfo->Type() == AudioDeviceInfo::TYPE_INPUT
982 ? MediaSourceEnum::Microphone
983 : MediaSourceEnum::Other),
984 mKind(mMediaSource == MediaSourceEnum::Microphone
985 ? MediaDeviceKind::Audioinput
986 : MediaDeviceKind::Audiooutput),
987 mScary(false),
988 mCanRequestOsLevelPrompt(false),
989 mIsFake(false),
990 mIsPlaceholder(false),
991 mType(NS_ConvertASCIItoUTF16(dom::GetEnumString(mKind))),
992 mRawID(aRawID),
993 mRawGroupID(mAudioDeviceInfo->GroupID()),
994 mRawName(mAudioDeviceInfo->Name()) {}
995
996/* static */
997RefPtr<MediaDevice> MediaDevice::CopyWithNewRawGroupId(
998 const RefPtr<MediaDevice>& aOther, const nsString& aRawGroupID) {
999 MOZ_ASSERT(!aOther->mAudioDeviceInfo, "device not supported")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aOther->mAudioDeviceInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aOther->mAudioDeviceInfo
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aOther->mAudioDeviceInfo" " (" "device not supported" ")"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 999); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOther->mAudioDeviceInfo" ") (" "device not supported"
")"); do { MOZ_CrashSequence(__null, 999); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1000 return new MediaDevice(aOther->mEngine, aOther->mMediaSource,
1001 aOther->mRawName, aOther->mRawID, aRawGroupID,
1002 IsScary(aOther->mScary),
1003 OsPromptable(aOther->mCanRequestOsLevelPrompt),
1004 IsPlaceholder(aOther->mIsPlaceholder));
1005}
1006
1007MediaDevice::~MediaDevice() = default;
1008
1009LocalMediaDevice::LocalMediaDevice(RefPtr<const MediaDevice> aRawDevice,
1010 const nsString& aID,
1011 const nsString& aGroupID,
1012 const nsString& aName)
1013 : mRawDevice(std::move(aRawDevice)),
1014 mName(aName),
1015 mID(aID),
1016 mGroupID(aGroupID) {
1017 MOZ_ASSERT(mRawDevice)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawDevice)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawDevice))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mRawDevice", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawDevice"
")"); do { MOZ_CrashSequence(__null, 1017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1018}
1019
1020/**
1021 * Helper functions that implement the constraints algorithm from
1022 * http://dev.w3.org/2011/webrtc/editor/getusermedia.html#methods-5
1023 */
1024
1025/* static */
1026bool LocalMediaDevice::StringsContain(
1027 const OwningStringOrStringSequence& aStrings, nsString aN) {
1028 return aStrings.IsString() ? aStrings.GetAsString() == aN
1029 : aStrings.GetAsStringSequence().Contains(aN);
1030}
1031
1032/* static */
1033uint32_t LocalMediaDevice::FitnessDistance(
1034 nsString aN, const ConstrainDOMStringParameters& aParams) {
1035 if (aParams.mExact.WasPassed() &&
1036 !StringsContain(aParams.mExact.Value(), aN)) {
1037 return UINT32_MAX(4294967295U);
1038 }
1039 if (aParams.mIdeal.WasPassed() &&
1040 !StringsContain(aParams.mIdeal.Value(), aN)) {
1041 return 1;
1042 }
1043 return 0;
1044}
1045
1046// Binding code doesn't templatize well...
1047
1048/* static */
1049uint32_t LocalMediaDevice::FitnessDistance(
1050 nsString aN,
1051 const OwningStringOrStringSequenceOrConstrainDOMStringParameters&
1052 aConstraint) {
1053 if (aConstraint.IsString()) {
1054 ConstrainDOMStringParameters params;
1055 params.mIdeal.Construct();
1056 params.mIdeal.Value().SetAsString() = aConstraint.GetAsString();
1057 return FitnessDistance(aN, params);
1058 } else if (aConstraint.IsStringSequence()) {
1059 ConstrainDOMStringParameters params;
1060 params.mIdeal.Construct();
1061 params.mIdeal.Value().SetAsStringSequence() =
1062 aConstraint.GetAsStringSequence();
1063 return FitnessDistance(aN, params);
1064 } else {
1065 return FitnessDistance(aN, aConstraint.GetAsConstrainDOMStringParameters());
1066 }
1067}
1068
1069uint32_t LocalMediaDevice::GetBestFitnessDistance(
1070 const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
1071 const MediaEnginePrefs& aPrefs, CallerType aCallerType) {
1072 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 1072); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1073 MOZ_ASSERT(GetMediaSource() != MediaSourceEnum::Other)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetMediaSource() != MediaSourceEnum::Other)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(GetMediaSource() != MediaSourceEnum::Other))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("GetMediaSource() != MediaSourceEnum::Other"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1073); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetMediaSource() != MediaSourceEnum::Other"
")"); do { MOZ_CrashSequence(__null, 1073); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1074
1075 bool isChrome = aCallerType == CallerType::System;
1076 const nsString& id = isChrome ? RawID() : mID;
1077 auto type = GetMediaSource();
1078 uint64_t distance = 0;
1079 if (!aConstraintSets.IsEmpty()) {
1080 if (isChrome /* For the screen/window sharing preview */ ||
1081 type == MediaSourceEnum::Camera ||
1082 type == MediaSourceEnum::Microphone) {
1083 distance += uint64_t(MediaConstraintsHelper::FitnessDistance(
1084 Some(id), aConstraintSets[0]->mDeviceId)) +
1085 uint64_t(MediaConstraintsHelper::FitnessDistance(
1086 Some(mGroupID), aConstraintSets[0]->mGroupId));
1087 }
1088 }
1089 if (distance < UINT32_MAX(4294967295U)) {
1090 // Forward request to underlying object to interrogate per-mode
1091 // capabilities.
1092 distance += Source()->GetBestFitnessDistance(aConstraintSets, aPrefs);
1093 }
1094 return std::min<uint64_t>(distance, UINT32_MAX(4294967295U));
1095}
1096
1097NS_IMETHODIMPnsresult
1098LocalMediaDevice::GetRawName(nsAString& aName) {
1099 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/MediaManager.cpp", 1099); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1099); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1100 aName.Assign(mRawDevice->mRawName);
1101 return NS_OK;
1102}
1103
1104NS_IMETHODIMPnsresult
1105LocalMediaDevice::GetType(nsAString& aType) {
1106 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/MediaManager.cpp", 1106); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1106); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1107 aType.Assign(mRawDevice->mType);
1108 return NS_OK;
1109}
1110
1111NS_IMETHODIMPnsresult
1112LocalMediaDevice::GetRawId(nsAString& aID) {
1113 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/MediaManager.cpp", 1113); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1113); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1114 aID.Assign(RawID());
1115 return NS_OK;
1116}
1117
1118NS_IMETHODIMPnsresult
1119LocalMediaDevice::GetId(nsAString& aID) {
1120 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/MediaManager.cpp", 1120); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1120); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1121 aID.Assign(mID);
1122 return NS_OK;
1123}
1124
1125NS_IMETHODIMPnsresult
1126LocalMediaDevice::GetScary(bool* aScary) {
1127 *aScary = mRawDevice->mScary;
1128 return NS_OK;
1129}
1130
1131NS_IMETHODIMPnsresult
1132LocalMediaDevice::GetCanRequestOsLevelPrompt(bool* aCanRequestOsLevelPrompt) {
1133 *aCanRequestOsLevelPrompt = mRawDevice->mCanRequestOsLevelPrompt;
1134 return NS_OK;
1135}
1136
1137void LocalMediaDevice::GetSettings(MediaTrackSettings& aOutSettings) {
1138 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/MediaManager.cpp", 1138); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1138); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1139 Source()->GetSettings(aOutSettings);
1140}
1141
1142void LocalMediaDevice::GetCapabilities(
1143 MediaTrackCapabilities& aOutCapabilities) {
1144 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/MediaManager.cpp", 1144); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1144); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1145 Source()->GetCapabilities(aOutCapabilities);
1146}
1147
1148MediaEngineSource* LocalMediaDevice::Source() {
1149 if (!mSource) {
1150 mSource = mRawDevice->mEngine->CreateSource(mRawDevice);
1151 }
1152 return mSource;
1153}
1154
1155const TrackingId& LocalMediaDevice::GetTrackingId() const {
1156 return mSource->GetTrackingId();
1157}
1158
1159// Threadsafe since mKind and mSource are const.
1160NS_IMETHODIMPnsresult
1161LocalMediaDevice::GetMediaSource(nsAString& aMediaSource) {
1162 if (Kind() == MediaDeviceKind::Audiooutput) {
1163 aMediaSource.Truncate();
1164 } else {
1165 aMediaSource.AssignASCII(dom::GetEnumString(GetMediaSource()));
1166 }
1167 return NS_OK;
1168}
1169
1170nsresult LocalMediaDevice::Allocate(const MediaTrackConstraints& aConstraints,
1171 const MediaEnginePrefs& aPrefs,
1172 uint64_t aWindowID,
1173 const char** aOutBadConstraint) {
1174 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 1174); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1175
1176 // Mock failure for automated tests.
1177 if (IsFake() && aConstraints.mDeviceId.WasPassed() &&
1178 aConstraints.mDeviceId.Value().IsString() &&
1179 aConstraints.mDeviceId.Value().GetAsString().EqualsASCII("bad device")) {
1180 return NS_ERROR_FAILURE;
1181 }
1182
1183 return Source()->Allocate(aConstraints, aPrefs, aWindowID, aOutBadConstraint);
1184}
1185
1186void LocalMediaDevice::SetTrack(const RefPtr<MediaTrack>& aTrack,
1187 const PrincipalHandle& aPrincipalHandle) {
1188 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1188); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 1188); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1189 Source()->SetTrack(aTrack, aPrincipalHandle);
1190}
1191
1192nsresult LocalMediaDevice::Start() {
1193 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 1193); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1194 MOZ_ASSERT(Source())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(Source())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(Source()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("Source()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Source()" ")"
); do { MOZ_CrashSequence(__null, 1194); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1195 return Source()->Start();
1196}
1197
1198nsresult LocalMediaDevice::Reconfigure(
1199 const MediaTrackConstraints& aConstraints, const MediaEnginePrefs& aPrefs,
1200 const char** aOutBadConstraint) {
1201 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 1201); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1202 using H = MediaConstraintsHelper;
1203 auto type = GetMediaSource();
1204 if (type == MediaSourceEnum::Camera || type == MediaSourceEnum::Microphone) {
1205 NormalizedConstraints c(aConstraints);
1206 if (H::FitnessDistance(Some(mID), c.mDeviceId) == UINT32_MAX(4294967295U)) {
1207 *aOutBadConstraint = "deviceId";
1208 return NS_ERROR_INVALID_ARG;
1209 }
1210 if (H::FitnessDistance(Some(mGroupID), c.mGroupId) == UINT32_MAX(4294967295U)) {
1211 *aOutBadConstraint = "groupId";
1212 return NS_ERROR_INVALID_ARG;
1213 }
1214 if (aPrefs.mResizeModeEnabled && type == MediaSourceEnum::Camera) {
1215 // Check invalid exact resizeMode constraint (not a device property)
1216 nsString none =
1217 NS_ConvertASCIItoUTF16(dom::GetEnumString(VideoResizeModeEnum::None));
1218 nsString crop = NS_ConvertASCIItoUTF16(
1219 dom::GetEnumString(VideoResizeModeEnum::Crop_and_scale));
1220 if (H::FitnessDistance(Some(none), c.mResizeMode) == UINT32_MAX(4294967295U) &&
1221 H::FitnessDistance(Some(crop), c.mResizeMode) == UINT32_MAX(4294967295U)) {
1222 *aOutBadConstraint = "resizeMode";
1223 return NS_ERROR_INVALID_ARG;
1224 }
1225 }
1226 }
1227 return Source()->Reconfigure(aConstraints, aPrefs, aOutBadConstraint);
1228}
1229
1230nsresult LocalMediaDevice::FocusOnSelectedSource() {
1231 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 1231); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1232 return Source()->FocusOnSelectedSource();
1233}
1234
1235nsresult LocalMediaDevice::Stop() {
1236 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 1236); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1237 MOZ_ASSERT(mSource)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSource)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSource))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mSource", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSource" ")"
); do { MOZ_CrashSequence(__null, 1237); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1238 return mSource->Stop();
1239}
1240
1241nsresult LocalMediaDevice::Deallocate() {
1242 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1242); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 1242); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1243 MOZ_ASSERT(mSource)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSource)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSource))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mSource", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1243); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSource" ")"
); do { MOZ_CrashSequence(__null, 1243); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1244 return mSource->Deallocate();
1245}
1246
1247MediaSourceEnum MediaDevice::GetMediaSource() const { return mMediaSource; }
1248
1249static const MediaTrackConstraints& GetInvariant(
1250 const OwningBooleanOrMediaTrackConstraints& aUnion) {
1251 static const MediaTrackConstraints empty;
1252 return aUnion.IsMediaTrackConstraints() ? aUnion.GetAsMediaTrackConstraints()
1253 : empty;
1254}
1255
1256// Source getter returning full list
1257
1258static void GetMediaDevices(MediaEngine* aEngine, MediaSourceEnum aSrcType,
1259 MediaManager::MediaDeviceSet& aResult,
1260 const char* aMediaDeviceName = nullptr) {
1261 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1261); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 1261); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1262
1263 LOG("%s: aEngine=%p, aSrcType=%" PRIu8"u" ", aMediaDeviceName=%s", __func__,
1264 aEngine, static_cast<uint8_t>(aSrcType),
1265 aMediaDeviceName ? aMediaDeviceName : "null");
1266 nsTArray<RefPtr<MediaDevice>> devices;
1267 aEngine->EnumerateDevices(aSrcType, MediaSinkEnum::Other, &devices);
1268
1269 /*
1270 * We're allowing multiple tabs to access the same camera for parity
1271 * with Chrome. See bug 811757 for some of the issues surrounding
1272 * this decision. To disallow, we'd filter by IsAvailable() as we used
1273 * to.
1274 */
1275 if (aMediaDeviceName && *aMediaDeviceName) {
1276 for (auto& device : devices) {
1277 if (device->mRawName.EqualsASCII(aMediaDeviceName)) {
1278 aResult.AppendElement(device);
1279 LOG("%s: found aMediaDeviceName=%s", __func__, aMediaDeviceName);
1280 break;
1281 }
1282 }
1283 } else {
1284 aResult = std::move(devices);
1285 if (MOZ_LOG_TEST(gMediaManagerLog, mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gMediaManagerLog
, mozilla::LogLevel::Debug)), 0))
) {
1286 for (auto& device : aResult) {
1287 LOG("%s: appending device=%s", __func__,
1288 NS_ConvertUTF16toUTF8(device->mRawName).get());
1289 }
1290 }
1291 }
1292}
1293
1294RefPtr<LocalDeviceSetPromise> MediaManager::SelectSettings(
1295 const MediaStreamConstraints& aConstraints, CallerType aCallerType,
1296 RefPtr<LocalMediaDeviceSetRefCnt> aDevices) {
1297 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/MediaManager.cpp", 1297); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1297); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1298
1299 // Algorithm accesses device capabilities code and must run on media thread.
1300 // Modifies passed-in aDevices.
1301
1302 return MediaManager::Dispatch<LocalDeviceSetPromise>(
1303 __func__, [aConstraints, devices = std::move(aDevices), prefs = mPrefs,
1304 aCallerType](MozPromiseHolder<LocalDeviceSetPromise>& holder) {
1305 auto& devicesRef = *devices;
1306
1307 // Since the advanced part of the constraints algorithm needs to know
1308 // when a candidate set is overconstrained (zero members), we must split
1309 // up the list into videos and audios, and put it back together again at
1310 // the end.
1311
1312 nsTArray<RefPtr<LocalMediaDevice>> videos;
1313 nsTArray<RefPtr<LocalMediaDevice>> audios;
1314
1315 for (const auto& device : devicesRef) {
1316 MOZ_ASSERT(device->Kind() == MediaDeviceKind::Videoinput ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(device->Kind() == MediaDeviceKind::Videoinput || device
->Kind() == MediaDeviceKind::Audioinput)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(device->Kind() == MediaDeviceKind
::Videoinput || device->Kind() == MediaDeviceKind::Audioinput
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1317); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput"
")"); do { MOZ_CrashSequence(__null, 1317); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1317 device->Kind() == MediaDeviceKind::Audioinput)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(device->Kind() == MediaDeviceKind::Videoinput || device
->Kind() == MediaDeviceKind::Audioinput)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(device->Kind() == MediaDeviceKind
::Videoinput || device->Kind() == MediaDeviceKind::Audioinput
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1317); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput"
")"); do { MOZ_CrashSequence(__null, 1317); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1318 if (device->Kind() == MediaDeviceKind::Videoinput) {
1319 videos.AppendElement(device);
1320 } else if (device->Kind() == MediaDeviceKind::Audioinput) {
1321 audios.AppendElement(device);
1322 }
1323 }
1324 devicesRef.Clear();
1325 const char* badConstraint = nullptr;
1326 bool needVideo = IsOn(aConstraints.mVideo);
1327 bool needAudio = IsOn(aConstraints.mAudio);
1328
1329 if (needVideo && videos.Length()) {
1330 badConstraint = MediaConstraintsHelper::SelectSettings(
1331 NormalizedConstraints(GetInvariant(aConstraints.mVideo)), prefs,
1332 videos, aCallerType);
1333 }
1334 if (!badConstraint && needAudio && audios.Length()) {
1335 badConstraint = MediaConstraintsHelper::SelectSettings(
1336 NormalizedConstraints(GetInvariant(aConstraints.mAudio)), prefs,
1337 audios, aCallerType);
1338 }
1339 if (badConstraint) {
1340 LOG("SelectSettings: bad constraint found! Calling error handler!");
1341 nsString constraint;
1342 constraint.AssignASCII(badConstraint);
1343 holder.Reject(
1344 new MediaMgrError(MediaMgrError::Name::OverconstrainedError, "",
1345 constraint),
1346 __func__);
1347 return;
1348 }
1349 if (!needVideo == !videos.Length() && !needAudio == !audios.Length()) {
1350 for (auto& video : videos) {
1351 devicesRef.AppendElement(video);
1352 }
1353 for (auto& audio : audios) {
1354 devicesRef.AppendElement(audio);
1355 }
1356 }
1357 holder.Resolve(devices, __func__);
1358 });
1359}
1360
1361/**
1362 * Describes a requested task that handles response from the UI and sends
1363 * results back to the DOM.
1364 */
1365class GetUserMediaTask {
1366 public:
1367 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GetUserMediaTask)public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<GetUserMediaTask>, "Reference-counted class "
"GetUserMediaTask" " 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/MediaManager.cpp"
, 1367); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 1367
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("GetUserMediaTask"), (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/dom/media/MediaManager.cpp"
, 1367); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1367
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("GetUserMediaTask")); if (count == 0) { delete (this
); return 0; } return count; } using HasThreadSafeRefCnt = std
::true_type; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt
; public:
1368 GetUserMediaTask(uint64_t aWindowID, const ipc::PrincipalInfo& aPrincipalInfo,
1369 CallerType aCallerType)
1370 : mPrincipalInfo(aPrincipalInfo),
1371 mWindowID(aWindowID),
1372 mCallerType(aCallerType) {}
1373
1374 virtual void Denied(MediaMgrError::Name aName,
1375 const nsCString& aMessage = ""_ns) = 0;
1376
1377 virtual GetUserMediaStreamTask* AsGetUserMediaStreamTask() { return nullptr; }
1378 virtual SelectAudioOutputTask* AsSelectAudioOutputTask() { return nullptr; }
1379
1380 uint64_t GetWindowID() const { return mWindowID; }
1381 enum CallerType CallerType() const { return mCallerType; }
1382
1383 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
1384 size_t amount = aMallocSizeOf(this);
1385 // Assume mWindowListener is owned by MediaManager.
1386 // Assume mAudioDeviceListener and mVideoDeviceListener are owned by
1387 // mWindowListener.
1388 // Assume PrincipalInfo string buffers are shared.
1389 // Member types without support for accounting of pointees:
1390 // MozPromiseHolder, RefPtr<LocalMediaDevice>.
1391 // We don't have a good way to account for lambda captures for MozPromise
1392 // callbacks.
1393 return amount;
1394 }
1395
1396 protected:
1397 virtual ~GetUserMediaTask() = default;
1398
1399 // Call GetPrincipalKey again, if not private browing, this time with
1400 // persist = true, to promote deviceIds to persistent, in case they're not
1401 // already. Fire'n'forget.
1402 void PersistPrincipalKey() {
1403 if (IsPrincipalInfoPrivate(mPrincipalInfo)) {
1404 return;
1405 }
1406 media::GetPrincipalKey(mPrincipalInfo, true)
1407 ->Then(
1408 GetCurrentSerialEventTarget(), __func__,
1409 [](const media::PrincipalKeyPromise::ResolveOrRejectValue& aValue) {
1410 if (aValue.IsReject()) {
1411 LOG("Failed get Principal key. Persisting of deviceIds "
1412 "will be broken");
1413 }
1414 });
1415 }
1416
1417 private:
1418 // Thread-safe (object) principal of Window with ID mWindowID
1419 const ipc::PrincipalInfo mPrincipalInfo;
1420
1421 protected:
1422 // The ID of the not-necessarily-toplevel inner Window relevant global
1423 // object of the MediaDevices on which getUserMedia() was called
1424 const uint64_t mWindowID;
1425 // Whether the JS caller of getUserMedia() has system (subject) principal
1426 const enum CallerType mCallerType;
1427};
1428
1429/**
1430 * Describes a requested task that handles response from the UI to a
1431 * getUserMedia() request and sends results back to content. If the request
1432 * is allowed and device initialization succeeds, then the MozPromise is
1433 * resolved with a DOMMediaStream having a track or tracks for the approved
1434 * device or devices.
1435 */
1436class GetUserMediaStreamTask final : public GetUserMediaTask {
1437 public:
1438 GetUserMediaStreamTask(
1439 const MediaStreamConstraints& aConstraints,
1440 MozPromiseHolder<MediaManager::StreamPromise>&& aHolder,
1441 uint64_t aWindowID, RefPtr<GetUserMediaWindowListener> aWindowListener,
1442 RefPtr<DeviceListener> aAudioDeviceListener,
1443 RefPtr<DeviceListener> aVideoDeviceListener,
1444 const MediaEnginePrefs& aPrefs, const ipc::PrincipalInfo& aPrincipalInfo,
1445 enum CallerType aCallerType, bool aShouldFocusSource)
1446 : GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType),
1447 mConstraints(aConstraints),
1448 mHolder(std::move(aHolder)),
1449 mWindowListener(std::move(aWindowListener)),
1450 mAudioDeviceListener(std::move(aAudioDeviceListener)),
1451 mVideoDeviceListener(std::move(aVideoDeviceListener)),
1452 mPrefs(aPrefs),
1453 mShouldFocusSource(aShouldFocusSource),
1454 mManager(MediaManager::GetInstance()) {}
1455
1456 void Allowed(RefPtr<LocalMediaDevice> aAudioDevice,
1457 RefPtr<LocalMediaDevice> aVideoDevice) {
1458 MOZ_ASSERT(aAudioDevice || aVideoDevice)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aAudioDevice || aVideoDevice)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aAudioDevice || aVideoDevice
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aAudioDevice || aVideoDevice", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioDevice || aVideoDevice"
")"); do { MOZ_CrashSequence(__null, 1458); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1459 mAudioDevice = std::move(aAudioDevice);
1460 mVideoDevice = std::move(aVideoDevice);
1461 // Reuse the same thread to save memory.
1462 MediaManager::Dispatch(
1463 NewRunnableMethod("GetUserMediaStreamTask::AllocateDevices", this,
1464 &GetUserMediaStreamTask::AllocateDevices));
1465 }
1466
1467 GetUserMediaStreamTask* AsGetUserMediaStreamTask() override { return this; }
1468
1469 private:
1470 ~GetUserMediaStreamTask() override {
1471 if (!mHolder.IsEmpty()) {
1472 Fail(MediaMgrError::Name::NotAllowedError);
1473 }
1474 }
1475
1476 void Fail(MediaMgrError::Name aName, const nsCString& aMessage = ""_ns,
1477 const nsString& aConstraint = u""_ns) {
1478 mHolder.Reject(MakeRefPtr<MediaMgrError>(aName, aMessage, aConstraint),
1479 __func__);
1480 // We add a disabled listener to the StreamListeners array until accepted
1481 // If this was the only active MediaStream, remove the window from the list.
1482 NS_DispatchToMainThread(NS_NewRunnableFunction(
1483 "DeviceListener::Stop",
1484 [audio = mAudioDeviceListener, video = mVideoDeviceListener] {
1485 if (audio) {
1486 audio->Stop();
1487 }
1488 if (video) {
1489 video->Stop();
1490 }
1491 }));
1492 }
1493
1494 /**
1495 * Runs on a separate thread and is responsible for allocating devices.
1496 *
1497 * Do not run this on the main thread.
1498 */
1499 void AllocateDevices() {
1500 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/MediaManager.cpp", 1500); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1500); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1501 LOG("GetUserMediaStreamTask::AllocateDevices()");
1502
1503 // Allocate a video or audio device and return a MediaStream via
1504 // PrepareDOMStream().
1505
1506 nsresult rv;
1507 const char* errorMsg = nullptr;
1508 const char* badConstraint = nullptr;
1509
1510 if (mAudioDevice) {
1511 auto& constraints = GetInvariant(mConstraints.mAudio);
1512 rv = mAudioDevice->Allocate(constraints, mPrefs, mWindowID,
1513 &badConstraint);
1514 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1515 errorMsg = "Failed to allocate audiosource";
1516 if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
1517 nsTArray<RefPtr<LocalMediaDevice>> devices;
1518 devices.AppendElement(mAudioDevice);
1519 badConstraint = MediaConstraintsHelper::SelectSettings(
1520 NormalizedConstraints(constraints), mPrefs, devices, mCallerType);
1521 }
1522 }
1523 }
1524 if (!errorMsg && mVideoDevice) {
1525 auto& constraints = GetInvariant(mConstraints.mVideo);
1526 rv = mVideoDevice->Allocate(constraints, mPrefs, mWindowID,
1527 &badConstraint);
1528 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1529 errorMsg = "Failed to allocate videosource";
1530 if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
1531 nsTArray<RefPtr<LocalMediaDevice>> devices;
1532 devices.AppendElement(mVideoDevice);
1533 badConstraint = MediaConstraintsHelper::SelectSettings(
1534 NormalizedConstraints(constraints), mPrefs, devices, mCallerType);
1535 }
1536 if (mAudioDevice) {
1537 mAudioDevice->Deallocate();
1538 }
1539 } else {
1540 mVideoTrackingId.emplace(mVideoDevice->GetTrackingId());
1541 }
1542 }
1543 if (errorMsg) {
1544 LOG("%s %" PRIu32"u", errorMsg, static_cast<uint32_t>(rv));
1545 if (badConstraint) {
1546 Fail(MediaMgrError::Name::OverconstrainedError, ""_ns,
1547 NS_ConvertUTF8toUTF16(badConstraint));
1548 } else {
1549 Fail(MediaMgrError::Name::NotReadableError, nsCString(errorMsg));
1550 }
1551 NS_DispatchToMainThread(
1552 NS_NewRunnableFunction("MediaManager::SendPendingGUMRequest", []() {
1553 if (MediaManager* manager = MediaManager::GetIfExists()) {
1554 manager->SendPendingGUMRequest();
1555 }
1556 }));
1557 return;
1558 }
1559 NS_DispatchToMainThread(
1560 NewRunnableMethod("GetUserMediaStreamTask::PrepareDOMStream", this,
1561 &GetUserMediaStreamTask::PrepareDOMStream));
1562 }
1563
1564 public:
1565 void Denied(MediaMgrError::Name aName, const nsCString& aMessage) override {
1566 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/MediaManager.cpp", 1566); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1566); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1567 Fail(aName, aMessage);
1568 }
1569
1570 const MediaStreamConstraints& GetConstraints() { return mConstraints; }
1571
1572 void PrimeVoiceProcessing() {
1573 mPrimingStream = MakeAndAddRef<PrimingCubebVoiceInputStream>();
1574 mPrimingStream->Init();
1575 }
1576
1577 private:
1578 void PrepareDOMStream();
1579
1580 class PrimingCubebVoiceInputStream {
1581 class Listener final : public CubebInputStream::Listener {
1582 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Listener, override)public: MozExternalRefCountType AddRef(void) override { static_assert
(!std::is_destructible_v<Listener>, "Reference-counted class "
"Listener" " 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/MediaManager.cpp"
, 1582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 1582
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("Listener"), (uint32_t)(sizeof(*this))); return (nsrefcnt
)count; } MozExternalRefCountType Release(void) override { 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/MediaManager.cpp"
, 1582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1582
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("Listener")); if (count == 0) { delete (this); return
0; } return count; } using HasThreadSafeRefCnt = std::true_type
; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public:
;
1583
1584 private:
1585 ~Listener() = default;
1586
1587 long DataCallback(const void*, long) override {
1588 MOZ_CRASH("Unexpected data callback")do { do { } while (false); MOZ_ReportCrash("" "Unexpected data callback"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1588); AnnotateMozCrashReason
("MOZ_CRASH(" "Unexpected data callback" ")"); do { MOZ_CrashSequence
(__null, 1588); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
1589 }
1590 void StateCallback(cubeb_state) override {}
1591 void DeviceChangedCallback() override {}
1592 };
1593
1594 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_EVENT_TARGET(public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<PrimingCubebVoiceInputStream>, "Reference-counted class "
"PrimingCubebVoiceInputStream" " 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/MediaManager.cpp"
, 1595); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 1595
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("PrimingCubebVoiceInputStream"), (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/dom/media/MediaManager.cpp"
, 1595); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1595
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("PrimingCubebVoiceInputStream")); if (count == 0) { ::
mozilla::detail::ProxyDeleteVoid( "ProxyDelete " "PrimingCubebVoiceInputStream"
, mCubebThread.GetEventTarget(), this, [](void* self) { delete
static_cast<PrimingCubebVoiceInputStream*>(self); }); return
0; } return count; } using HasThreadSafeRefCnt = std::true_type
; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public:
1595 PrimingCubebVoiceInputStream, mCubebThread.GetEventTarget())public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<PrimingCubebVoiceInputStream>, "Reference-counted class "
"PrimingCubebVoiceInputStream" " 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/MediaManager.cpp"
, 1595); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 1595
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("PrimingCubebVoiceInputStream"), (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/dom/media/MediaManager.cpp"
, 1595); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 1595
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("PrimingCubebVoiceInputStream")); if (count == 0) { ::
mozilla::detail::ProxyDeleteVoid( "ProxyDelete " "PrimingCubebVoiceInputStream"
, mCubebThread.GetEventTarget(), this, [](void* self) { delete
static_cast<PrimingCubebVoiceInputStream*>(self); }); return
0; } return count; } using HasThreadSafeRefCnt = std::true_type
; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public:
1596
1597 public:
1598 void Init() {
1599 mCubebThread.GetEventTarget()->Dispatch(
1600 NS_NewRunnableFunction(__func__, [this, self = RefPtr(this)] {
1601 mCubebThread.AssertOnCurrentThread();
1602 LOG("Priming voice processing with stream %p", this);
1603 TRACE("PrimingCubebVoiceInputStream::Init")AutoTracer trace(gAudioCallbackTraceLogger, "PrimingCubebVoiceInputStream::Init"
);
;
1604 const cubeb_devid default_device = nullptr;
1605 const uint32_t mono = 1;
1606 const uint32_t rate = CubebUtils::PreferredSampleRate(false);
1607 const bool isVoice = true;
1608 mCubebStream =
1609 CubebInputStream::Create(default_device, mono, rate, isVoice,
1610 MakeRefPtr<Listener>().get());
1611 }));
1612 }
1613
1614 private:
1615 ~PrimingCubebVoiceInputStream() {
1616 mCubebThread.AssertOnCurrentThread();
1617 LOG("Releasing primed voice processing stream %p", this);
1618 mCubebStream = nullptr;
1619 }
1620
1621 const EventTargetCapability<nsISerialEventTarget> mCubebThread =
1622 EventTargetCapability<nsISerialEventTarget>(
1623 TaskQueue::Create(CubebUtils::GetCubebOperationThread(),
1624 "PrimingCubebInputStream::mCubebThread")
1625 .get());
1626 UniquePtr<CubebInputStream> mCubebStream MOZ_GUARDED_BY(mCubebThread)__attribute__((guarded_by(mCubebThread)));
1627 };
1628
1629 // Constraints derived from those passed to getUserMedia() but adjusted for
1630 // preferences, defaults, and security
1631 const MediaStreamConstraints mConstraints;
1632
1633 MozPromiseHolder<MediaManager::StreamPromise> mHolder;
1634 // GetUserMediaWindowListener with which DeviceListeners are registered
1635 const RefPtr<GetUserMediaWindowListener> mWindowListener;
1636 const RefPtr<DeviceListener> mAudioDeviceListener;
1637 const RefPtr<DeviceListener> mVideoDeviceListener;
1638 // MediaDevices are set when selected and Allowed() by the UI.
1639 RefPtr<LocalMediaDevice> mAudioDevice;
1640 RefPtr<LocalMediaDevice> mVideoDevice;
1641 RefPtr<PrimingCubebVoiceInputStream> mPrimingStream;
1642 // Tracking id unique for a video frame source. Set when the corresponding
1643 // device has been allocated.
1644 Maybe<TrackingId> mVideoTrackingId;
1645 // Copy of MediaManager::mPrefs
1646 const MediaEnginePrefs mPrefs;
1647 // media.getusermedia.window.focus_source.enabled
1648 const bool mShouldFocusSource;
1649 // The MediaManager is referenced at construction so that it won't be
1650 // created after its ShutdownBlocker would run.
1651 const RefPtr<MediaManager> mManager;
1652};
1653
1654/**
1655 * Creates a MediaTrack, attaches a listener and resolves a MozPromise to
1656 * provide the stream to the DOM.
1657 *
1658 * All of this must be done on the main thread!
1659 */
1660void GetUserMediaStreamTask::PrepareDOMStream() {
1661 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/MediaManager.cpp", 1661); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1661); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1662 LOG("GetUserMediaStreamTask::PrepareDOMStream()");
1663 nsGlobalWindowInner* window =
1664 nsGlobalWindowInner::GetInnerWindowWithId(mWindowID);
1665
1666 // We're on main-thread, and the windowlist can only
1667 // be invalidated from the main-thread (see OnNavigation)
1668 if (!mManager->IsWindowListenerStillActive(mWindowListener)) {
1669 // This window is no longer live. mListener has already been removed.
1670 return;
1671 }
1672
1673 MediaTrackGraph::GraphDriverType graphDriverType =
1674 mAudioDevice ? MediaTrackGraph::AUDIO_THREAD_DRIVER
1675 : MediaTrackGraph::SYSTEM_THREAD_DRIVER;
1676 MediaTrackGraph* mtg = MediaTrackGraph::GetInstance(
1677 graphDriverType, window, MediaTrackGraph::REQUEST_DEFAULT_SAMPLE_RATE,
1678 MediaTrackGraph::DEFAULT_OUTPUT_DEVICE);
1679
1680 auto domStream = MakeRefPtr<DOMMediaStream>(window);
1681 RefPtr<LocalTrackSource> audioTrackSource;
1682 RefPtr<LocalTrackSource> videoTrackSource;
1683 nsCOMPtr<nsIPrincipal> principal;
1684 RefPtr<PeerIdentity> peerIdentity = nullptr;
1685 if (!mConstraints.mPeerIdentity.IsEmpty()) {
1686 peerIdentity = new PeerIdentity(mConstraints.mPeerIdentity);
1687 principal = NullPrincipal::CreateWithInheritedAttributes(
1688 window->GetExtantDoc()->NodePrincipal());
1689 } else {
1690 principal = window->GetExtantDoc()->NodePrincipal();
1691 }
1692 RefPtr<GenericNonExclusivePromise> firstFramePromise;
1693 if (mAudioDevice) {
1694 if (mAudioDevice->GetMediaSource() == MediaSourceEnum::AudioCapture) {
1695 // AudioCapture is a special case, here, in the sense that we're not
1696 // really using the audio source and the SourceMediaTrack, which acts
1697 // as placeholders. We re-route a number of tracks internally in the
1698 // MTG and mix them down instead.
1699 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle "
"MediaSourceEnum::AudioCapture. This must be fixed with UX "
"before shipping.", nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1702)
1700 "MediaCaptureWindowState doesn't handle "NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle "
"MediaSourceEnum::AudioCapture. This must be fixed with UX "
"before shipping.", nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1702)
1701 "MediaSourceEnum::AudioCapture. This must be fixed with UX "NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle "
"MediaSourceEnum::AudioCapture. This must be fixed with UX "
"before shipping.", nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1702)
1702 "before shipping.")NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle "
"MediaSourceEnum::AudioCapture. This must be fixed with UX "
"before shipping.", nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1702)
;
1703 auto audioCaptureSource = MakeRefPtr<AudioCaptureTrackSource>(
1704 principal, window, u"Window audio capture"_ns,
1705 mtg->CreateAudioCaptureTrack(), peerIdentity);
1706 audioTrackSource = audioCaptureSource;
1707 RefPtr<MediaStreamTrack> track = new dom::AudioStreamTrack(
1708 window, audioCaptureSource->InputTrack(), audioCaptureSource);
1709 domStream->AddTrackInternal(track);
1710 } else {
1711 const nsString& audioDeviceName = mAudioDevice->mName;
1712 RefPtr<MediaTrack> track;
1713#ifdef MOZ_WEBRTC1
1714 if (mAudioDevice->IsFake()) {
1715 track = mtg->CreateSourceTrack(MediaSegment::AUDIO);
1716 } else {
1717 track = AudioProcessingTrack::Create(mtg);
1718 track->Suspend(); // Microphone source resumes in SetTrack
1719 }
1720#else
1721 track = mtg->CreateSourceTrack(MediaSegment::AUDIO);
1722#endif
1723 audioTrackSource = new LocalTrackSource(
1724 principal, audioDeviceName, mAudioDeviceListener,
1725 mAudioDevice->GetMediaSource(), track, peerIdentity);
1726 MOZ_ASSERT(MediaManager::IsOn(mConstraints.mAudio))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsOn(mConstraints.mAudio))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(MediaManager::IsOn(mConstraints.mAudio)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("MediaManager::IsOn(mConstraints.mAudio)"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1726); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "MediaManager::IsOn(mConstraints.mAudio)" ")"
); do { MOZ_CrashSequence(__null, 1726); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1727 RefPtr<MediaStreamTrack> domTrack = new dom::AudioStreamTrack(
1728 window, track, audioTrackSource, dom::MediaStreamTrackState::Live,
1729 false, GetInvariant(mConstraints.mAudio));
1730 domStream->AddTrackInternal(domTrack);
1731 }
1732 }
1733 if (mVideoDevice) {
1734 const nsString& videoDeviceName = mVideoDevice->mName;
1735 RefPtr<MediaTrack> track = mtg->CreateSourceTrack(MediaSegment::VIDEO);
1736 videoTrackSource = new LocalTrackSource(
1737 principal, videoDeviceName, mVideoDeviceListener,
1738 mVideoDevice->GetMediaSource(), track, peerIdentity, *mVideoTrackingId);
1739 MOZ_ASSERT(MediaManager::IsOn(mConstraints.mVideo))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsOn(mConstraints.mVideo))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(MediaManager::IsOn(mConstraints.mVideo)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("MediaManager::IsOn(mConstraints.mVideo)"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1739); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "MediaManager::IsOn(mConstraints.mVideo)" ")"
); do { MOZ_CrashSequence(__null, 1739); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1740 RefPtr<MediaStreamTrack> domTrack = new dom::VideoStreamTrack(
1741 window, track, videoTrackSource, dom::MediaStreamTrackState::Live,
1742 false, GetInvariant(mConstraints.mVideo));
1743 domStream->AddTrackInternal(domTrack);
1744 switch (mVideoDevice->GetMediaSource()) {
1745 case MediaSourceEnum::Browser:
1746 case MediaSourceEnum::Screen:
1747 case MediaSourceEnum::Window:
1748 // Wait for first frame for screen-sharing devices, to ensure
1749 // with and height settings are available immediately, to pass wpt.
1750 firstFramePromise = mVideoDevice->Source()->GetFirstFramePromise();
1751 break;
1752 default:
1753 break;
1754 }
1755 }
1756
1757 if (!domStream || (!audioTrackSource && !videoTrackSource) ||
1758 sHasMainThreadShutdown) {
1759 LOG("Returning error for getUserMedia() - no stream");
1760
1761 mHolder.Reject(
1762 MakeRefPtr<MediaMgrError>(
1763 MediaMgrError::Name::AbortError,
1764 sHasMainThreadShutdown ? "In shutdown"_ns : "No stream."_ns),
1765 __func__);
1766 return;
1767 }
1768
1769 // Activate our device listeners. We'll call Start() on the source when we
1770 // get a callback that the MediaStream has started consuming. The listener
1771 // is freed when the page is invalidated (on navigation or close).
1772 if (mAudioDeviceListener) {
1773 mWindowListener->Activate(mAudioDeviceListener, mAudioDevice,
1774 std::move(audioTrackSource));
1775 }
1776 if (mVideoDeviceListener) {
1777 mWindowListener->Activate(mVideoDeviceListener, mVideoDevice,
1778 std::move(videoTrackSource));
1779 }
1780
1781 // Dispatch to the media thread to ask it to start the sources, because that
1782 // can take a while.
1783 typedef DeviceListener::DeviceListenerPromise PromiseType;
1784 AutoTArray<RefPtr<PromiseType>, 2> promises;
1785 if (mAudioDeviceListener) {
1786 promises.AppendElement(mAudioDeviceListener->InitializeAsync());
1787 }
1788 if (mVideoDeviceListener) {
1789 promises.AppendElement(mVideoDeviceListener->InitializeAsync());
1790 }
1791 PromiseType::All(GetMainThreadSerialEventTarget(), promises)
1792 ->Then(
1793 GetMainThreadSerialEventTarget(), __func__,
1794 [manager = mManager, windowListener = mWindowListener,
1795 firstFramePromise] {
1796 LOG("GetUserMediaStreamTask::PrepareDOMStream: starting success "
1797 "callback following InitializeAsync()");
1798 // Initiating and starting devices succeeded.
1799 windowListener->ChromeAffectingStateChanged();
1800 manager->SendPendingGUMRequest();
1801 if (!firstFramePromise) {
1802 return DeviceListener::DeviceListenerPromise::CreateAndResolve(
1803 true, __func__);
1804 }
1805 RefPtr<DeviceListener::DeviceListenerPromise> resolvePromise =
1806 firstFramePromise->Then(
1807 GetMainThreadSerialEventTarget(), __func__,
1808 [] {
1809 return DeviceListener::DeviceListenerPromise::
1810 CreateAndResolve(true, __func__);
1811 },
1812 [](nsresult aError) {
1813 MOZ_ASSERT(NS_FAILED(aError))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aError)),
0))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aError)),
0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(NS_FAILED_impl(aError)), 0)))",
"/root/firefox-clang/dom/media/MediaManager.cpp", 1813); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aError)), 0)))"
")"); do { MOZ_CrashSequence(__null, 1813); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1814 if (aError == NS_ERROR_UNEXPECTED) {
1815 return DeviceListener::DeviceListenerPromise::
1816 CreateAndReject(
1817 MakeRefPtr<MediaMgrError>(
1818 MediaMgrError::Name::NotAllowedError),
1819 __func__);
1820 }
1821 MOZ_ASSERT(aError == NS_ERROR_ABORT)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aError == NS_ERROR_ABORT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aError == NS_ERROR_ABORT))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aError == NS_ERROR_ABORT"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1821); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aError == NS_ERROR_ABORT" ")"); do { MOZ_CrashSequence
(__null, 1821); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1822 return DeviceListener::DeviceListenerPromise::
1823 CreateAndReject(MakeRefPtr<MediaMgrError>(
1824 MediaMgrError::Name::AbortError,
1825 "In shutdown"),
1826 __func__);
1827 });
1828 return resolvePromise;
1829 },
1830 [audio = mAudioDeviceListener,
1831 video = mVideoDeviceListener](const RefPtr<MediaMgrError>& aError) {
1832 LOG("GetUserMediaStreamTask::PrepareDOMStream: starting failure "
1833 "callback following InitializeAsync()");
1834 if (audio) {
1835 audio->Stop();
1836 }
1837 if (video) {
1838 video->Stop();
1839 }
1840 return DeviceListener::DeviceListenerPromise::CreateAndReject(
1841 aError, __func__);
1842 })
1843 ->Then(
1844 GetMainThreadSerialEventTarget(), __func__,
1845 [holder = std::move(mHolder), domStream, callerType = mCallerType,
1846 shouldFocus = mShouldFocusSource, videoDevice = mVideoDevice](
1847 const DeviceListener::DeviceListenerPromise::ResolveOrRejectValue&
1848 aValue) mutable {
1849 if (aValue.IsResolve()) {
1850 if (auto* mgr = MediaManager::GetIfExists();
1851 mgr && !sHasMainThreadShutdown && videoDevice &&
1852 callerType == CallerType::NonSystem && shouldFocus) {
1853 // Device was successfully started. Attempt to focus the
1854 // source.
1855 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource"
, [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice
->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed"
); } })))), 1)))), 1))) { } else { do { do { } while (false);
MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1863); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1856 mgr->mMediaThread->Dispatch(NS_NewRunnableFunction(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource"
, [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice
->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed"
); } })))), 1)))), 1))) { } else { do { do { } while (false);
MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1863); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1857 "GetUserMediaStreamTask::FocusOnSelectedSource",do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource"
, [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice
->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed"
); } })))), 1)))), 1))) { } else { do { do { } while (false);
MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1863); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1858 [videoDevice = std::move(videoDevice)] {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource"
, [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice
->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed"
); } })))), 1)))), 1))) { } else { do { do { } while (false);
MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1863); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1859 nsresult rv = videoDevice->FocusOnSelectedSource();do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource"
, [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice
->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed"
); } })))), 1)))), 1))) { } else { do { do { } while (false);
MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1863); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1860 if (NS_FAILED(rv)) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource"
, [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice
->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed"
); } })))), 1)))), 1))) { } else { do { do { } while (false);
MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1863); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1861 LOG("FocusOnSelectedSource failed");do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource"
, [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice
->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed"
); } })))), 1)))), 1))) { } else { do { do { } while (false);
MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1863); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1862 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource"
, [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice
->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed"
); } })))), 1)))), 1))) { } else { do { do { } while (false);
MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1863); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1863 })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource"
, [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice
->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!
(NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed"
); } })))), 1)))), 1))) { } else { do { do { } while (false);
MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1863); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))"
")"); do { MOZ_CrashSequence(__null, 1863); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1864 }
1865
1866 holder.Resolve(domStream, __func__);
1867 } else {
1868 holder.Reject(aValue.RejectValue(), __func__);
1869 }
1870 });
1871
1872 PersistPrincipalKey();
1873}
1874
1875/**
1876 * Describes a requested task that handles response from the UI to a
1877 * selectAudioOutput() request and sends results back to content. If the
1878 * request is allowed, then the MozPromise is resolved with a MediaDevice
1879 * for the approved device.
1880 */
1881class SelectAudioOutputTask final : public GetUserMediaTask {
1882 public:
1883 SelectAudioOutputTask(MozPromiseHolder<LocalDevicePromise>&& aHolder,
1884 uint64_t aWindowID, enum CallerType aCallerType,
1885 const ipc::PrincipalInfo& aPrincipalInfo)
1886 : GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType),
1887 mHolder(std::move(aHolder)) {}
1888
1889 void Allowed(RefPtr<LocalMediaDevice> aAudioOutput) {
1890 MOZ_ASSERT(aAudioOutput)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aAudioOutput)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aAudioOutput))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aAudioOutput", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 1890); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioOutput"
")"); do { MOZ_CrashSequence(__null, 1890); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1891 mHolder.Resolve(std::move(aAudioOutput), __func__);
1892 PersistPrincipalKey();
1893 }
1894
1895 void Denied(MediaMgrError::Name aName, const nsCString& aMessage) override {
1896 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/MediaManager.cpp", 1896); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1896); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1897 Fail(aName, aMessage);
1898 }
1899
1900 SelectAudioOutputTask* AsSelectAudioOutputTask() override { return this; }
1901
1902 private:
1903 ~SelectAudioOutputTask() override {
1904 if (!mHolder.IsEmpty()) {
1905 Fail(MediaMgrError::Name::NotAllowedError);
1906 }
1907 }
1908
1909 void Fail(MediaMgrError::Name aName, const nsCString& aMessage = ""_ns) {
1910 mHolder.Reject(MakeRefPtr<MediaMgrError>(aName, aMessage), __func__);
1911 }
1912
1913 private:
1914 MozPromiseHolder<LocalDevicePromise> mHolder;
1915};
1916
1917/* static */
1918void MediaManager::GuessVideoDeviceGroupIDs(MediaDeviceSet& aDevices,
1919 const MediaDeviceSet& aAudios) {
1920 // Run the logic in a lambda to avoid duplication.
1921 auto updateGroupIdIfNeeded = [&](RefPtr<MediaDevice>& aVideo,
1922 const MediaDeviceKind aKind) -> bool {
1923 MOZ_ASSERT(aVideo->mKind == MediaDeviceKind::Videoinput)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aVideo->mKind == MediaDeviceKind::Videoinput)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aVideo->mKind == MediaDeviceKind::Videoinput))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aVideo->mKind == MediaDeviceKind::Videoinput"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1923); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aVideo->mKind == MediaDeviceKind::Videoinput"
")"); do { MOZ_CrashSequence(__null, 1923); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1924 MOZ_ASSERT(aKind == MediaDeviceKind::Audioinput ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind
::Audiooutput)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aKind == MediaDeviceKind::Audioinput
|| aKind == MediaDeviceKind::Audiooutput))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1925); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput"
")"); do { MOZ_CrashSequence(__null, 1925); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1925 aKind == MediaDeviceKind::Audiooutput)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind
::Audiooutput)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aKind == MediaDeviceKind::Audioinput
|| aKind == MediaDeviceKind::Audiooutput))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 1925); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput"
")"); do { MOZ_CrashSequence(__null, 1925); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1926 // This will store the new group id if a match is found.
1927 nsString newVideoGroupID;
1928 // If the group id needs to be updated this will become true. It is
1929 // necessary when the new group id is an empty string. Without this extra
1930 // variable to signal the update, we would resort to test if
1931 // `newVideoGroupId` is empty. However,
1932 // that check does not work when the new group id is an empty string.
1933 bool updateGroupId = false;
1934 for (const RefPtr<MediaDevice>& dev : aAudios) {
1935 if (dev->mKind != aKind) {
1936 continue;
1937 }
1938 if (!FindInReadable(aVideo->mRawName, dev->mRawName)) {
1939 continue;
1940 }
1941 if (newVideoGroupID.IsEmpty()) {
1942 // This is only expected on first match. If that's the only match group
1943 // id will be updated to this one at the end of the loop.
1944 updateGroupId = true;
1945 newVideoGroupID = dev->mRawGroupID;
1946 } else {
1947 // More than one device found, it is impossible to know which group id
1948 // is the correct one.
1949 updateGroupId = false;
1950 newVideoGroupID = u""_ns;
1951 break;
1952 }
1953 }
1954 if (updateGroupId) {
1955 aVideo = MediaDevice::CopyWithNewRawGroupId(aVideo, newVideoGroupID);
1956 return true;
1957 }
1958 return false;
1959 };
1960
1961 for (RefPtr<MediaDevice>& video : aDevices) {
1962 if (video->mKind != MediaDeviceKind::Videoinput) {
1963 continue;
1964 }
1965 if (updateGroupIdIfNeeded(video, MediaDeviceKind::Audioinput)) {
1966 // GroupId has been updated, continue to the next video device
1967 continue;
1968 }
1969 // GroupId has not been updated, check among the outputs
1970 updateGroupIdIfNeeded(video, MediaDeviceKind::Audiooutput);
1971 }
1972}
1973
1974namespace {
1975
1976// Class to hold the promise used to request device access and to resolve
1977// even if |task| does not run, either because GeckoViewPermissionProcessChild
1978// gets destroyed before ask-device-permission receives its
1979// got-device-permission reply, or because the media thread is no longer
1980// available. In either case, the process is shutting down so the result is
1981// not important. Reject with a dummy error so the following Then-handler can
1982// resolve with an empty set, so that callers do not need to handle rejection.
1983class DeviceAccessRequestPromiseHolderWithFallback
1984 : public MozPromiseHolder<MozPromise<
1985 CamerasAccessStatus, mozilla::ipc::ResponseRejectReason, true>> {
1986 public:
1987 DeviceAccessRequestPromiseHolderWithFallback() = default;
1988 DeviceAccessRequestPromiseHolderWithFallback(
1989 DeviceAccessRequestPromiseHolderWithFallback&&) = default;
1990 ~DeviceAccessRequestPromiseHolderWithFallback() {
1991 if (!IsEmpty()) {
1992 Reject(ipc::ResponseRejectReason::ChannelClosed, __func__);
1993 }
1994 }
1995};
1996
1997} // anonymous namespace
1998
1999MediaManager::DeviceEnumerationParams::DeviceEnumerationParams(
2000 dom::MediaSourceEnum aInputType, DeviceType aType,
2001 nsAutoCString aForcedDeviceName)
2002 : mInputType(aInputType),
2003 mType(aType),
2004 mForcedDeviceName(std::move(aForcedDeviceName)) {
2005 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/MediaManager.cpp", 2005); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2005); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2006 MOZ_ASSERT(mInputType != dom::MediaSourceEnum::Other)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInputType != dom::MediaSourceEnum::Other)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mInputType != dom::MediaSourceEnum::Other))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mInputType != dom::MediaSourceEnum::Other"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2006); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mInputType != dom::MediaSourceEnum::Other"
")"); do { MOZ_CrashSequence(__null, 2006); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2007 MOZ_ASSERT_IF(!mForcedDeviceName.IsEmpty(), mType == DeviceType::Real)do { if (!mForcedDeviceName.IsEmpty()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mType == DeviceType
::Real)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mType == DeviceType::Real))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mType == DeviceType::Real", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mType == DeviceType::Real"
")"); do { MOZ_CrashSequence(__null, 2007); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2008}
2009
2010MediaManager::VideoDeviceEnumerationParams::VideoDeviceEnumerationParams(
2011 dom::MediaSourceEnum aInputType, DeviceType aType,
2012 nsAutoCString aForcedDeviceName, nsAutoCString aForcedMicrophoneName)
2013 : DeviceEnumerationParams(aInputType, aType, std::move(aForcedDeviceName)),
2014 mForcedMicrophoneName(std::move(aForcedMicrophoneName)) {
2015 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/MediaManager.cpp", 2015); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2015); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2016 MOZ_ASSERT_IF(!mForcedMicrophoneName.IsEmpty(),do { if (!mForcedMicrophoneName.IsEmpty()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(mInputType
== dom::MediaSourceEnum::Camera)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInputType == dom::MediaSourceEnum
::Camera))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mInputType == dom::MediaSourceEnum::Camera", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInputType == dom::MediaSourceEnum::Camera"
")"); do { MOZ_CrashSequence(__null, 2017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2017 mInputType == dom::MediaSourceEnum::Camera)do { if (!mForcedMicrophoneName.IsEmpty()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(mInputType
== dom::MediaSourceEnum::Camera)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInputType == dom::MediaSourceEnum
::Camera))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mInputType == dom::MediaSourceEnum::Camera", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInputType == dom::MediaSourceEnum::Camera"
")"); do { MOZ_CrashSequence(__null, 2017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2018 MOZ_ASSERT_IF(!mForcedMicrophoneName.IsEmpty(), mType == DeviceType::Real)do { if (!mForcedMicrophoneName.IsEmpty()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(mType ==
DeviceType::Real)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mType == DeviceType::Real)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("mType == DeviceType::Real"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2018); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mType == DeviceType::Real" ")"); do { MOZ_CrashSequence
(__null, 2018); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
2019}
2020
2021MediaManager::EnumerationParams::EnumerationParams(
2022 EnumerationFlags aFlags, Maybe<VideoDeviceEnumerationParams> aVideo,
2023 Maybe<DeviceEnumerationParams> aAudio)
2024 : mFlags(aFlags), mVideo(std::move(aVideo)), mAudio(std::move(aAudio)) {
2025 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/MediaManager.cpp", 2025); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2025); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2026 MOZ_ASSERT_IF(mVideo, MediaEngineSource::IsVideo(mVideo->mInputType))do { if (mVideo) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(MediaEngineSource::IsVideo(mVideo->mInputType
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(MediaEngineSource::IsVideo(mVideo->mInputType))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaEngineSource::IsVideo(mVideo->mInputType)"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2026); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "MediaEngineSource::IsVideo(mVideo->mInputType)"
")"); do { MOZ_CrashSequence(__null, 2026); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2027 MOZ_ASSERT_IF(mVideo && !mVideo->mForcedDeviceName.IsEmpty(),do { if (mVideo && !mVideo->mForcedDeviceName.IsEmpty
()) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mVideo->mInputType == dom::MediaSourceEnum::Camera", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera"
")"); do { MOZ_CrashSequence(__null, 2028); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2028 mVideo->mInputType == dom::MediaSourceEnum::Camera)do { if (mVideo && !mVideo->mForcedDeviceName.IsEmpty
()) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mVideo->mInputType == dom::MediaSourceEnum::Camera", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera"
")"); do { MOZ_CrashSequence(__null, 2028); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2029 MOZ_ASSERT_IF(mVideo && mVideo->mType == DeviceType::Fake,do { if (mVideo && mVideo->mType == DeviceType::Fake
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mVideo->mInputType == dom::MediaSourceEnum::Camera", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2030); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera"
")"); do { MOZ_CrashSequence(__null, 2030); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2030 mVideo->mInputType == dom::MediaSourceEnum::Camera)do { if (mVideo && mVideo->mType == DeviceType::Fake
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mVideo->mInputType == dom::MediaSourceEnum::Camera", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2030); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera"
")"); do { MOZ_CrashSequence(__null, 2030); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2031 MOZ_ASSERT_IF(mAudio, MediaEngineSource::IsAudio(mAudio->mInputType))do { if (mAudio) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(MediaEngineSource::IsAudio(mAudio->mInputType
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(MediaEngineSource::IsAudio(mAudio->mInputType))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaEngineSource::IsAudio(mAudio->mInputType)"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2031); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "MediaEngineSource::IsAudio(mAudio->mInputType)"
")"); do { MOZ_CrashSequence(__null, 2031); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2032 MOZ_ASSERT_IF(mAudio && !mAudio->mForcedDeviceName.IsEmpty(),do { if (mAudio && !mAudio->mForcedDeviceName.IsEmpty
()) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone"
")"); do { MOZ_CrashSequence(__null, 2033); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2033 mAudio->mInputType == dom::MediaSourceEnum::Microphone)do { if (mAudio && !mAudio->mForcedDeviceName.IsEmpty
()) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone"
")"); do { MOZ_CrashSequence(__null, 2033); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2034 MOZ_ASSERT_IF(mAudio && mAudio->mType == DeviceType::Fake,do { if (mAudio && mAudio->mType == DeviceType::Fake
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2035); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone"
")"); do { MOZ_CrashSequence(__null, 2035); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2035 mAudio->mInputType == dom::MediaSourceEnum::Microphone)do { if (mAudio && mAudio->mType == DeviceType::Fake
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2035); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone"
")"); do { MOZ_CrashSequence(__null, 2035); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2036}
2037
2038bool MediaManager::EnumerationParams::HasFakeCams() const {
2039 return mVideo
2040 .map([](const auto& aDev) { return aDev.mType == DeviceType::Fake; })
2041 .valueOr(false);
2042}
2043
2044bool MediaManager::EnumerationParams::HasFakeMics() const {
2045 return mAudio
2046 .map([](const auto& aDev) { return aDev.mType == DeviceType::Fake; })
2047 .valueOr(false);
2048}
2049
2050bool MediaManager::EnumerationParams::RealDeviceRequested() const {
2051 auto isReal = [](const auto& aDev) { return aDev.mType == DeviceType::Real; };
2052 return mVideo.map(isReal).valueOr(false) ||
2053 mAudio.map(isReal).valueOr(false) ||
2054 mFlags.contains(EnumerationFlag::EnumerateAudioOutputs);
2055}
2056
2057MediaSourceEnum MediaManager::EnumerationParams::VideoInputType() const {
2058 return mVideo.map([](const auto& aDev) { return aDev.mInputType; })
2059 .valueOr(MediaSourceEnum::Other);
2060}
2061
2062MediaSourceEnum MediaManager::EnumerationParams::AudioInputType() const {
2063 return mAudio.map([](const auto& aDev) { return aDev.mInputType; })
2064 .valueOr(MediaSourceEnum::Other);
2065}
2066
2067/* static */ MediaManager::EnumerationParams
2068MediaManager::CreateEnumerationParams(dom::MediaSourceEnum aVideoInputType,
2069 dom::MediaSourceEnum aAudioInputType,
2070 EnumerationFlags aFlags) {
2071 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/MediaManager.cpp", 2071); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2071); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2072 MOZ_ASSERT_IF(!MediaEngineSource::IsVideo(aVideoInputType),do { if (!MediaEngineSource::IsVideo(aVideoInputType)) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(aVideoInputType == dom::MediaSourceEnum::Other)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aVideoInputType == dom::MediaSourceEnum::Other))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aVideoInputType == dom::MediaSourceEnum::Other"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2073); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aVideoInputType == dom::MediaSourceEnum::Other"
")"); do { MOZ_CrashSequence(__null, 2073); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2073 aVideoInputType == dom::MediaSourceEnum::Other)do { if (!MediaEngineSource::IsVideo(aVideoInputType)) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(aVideoInputType == dom::MediaSourceEnum::Other)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aVideoInputType == dom::MediaSourceEnum::Other))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aVideoInputType == dom::MediaSourceEnum::Other"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2073); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aVideoInputType == dom::MediaSourceEnum::Other"
")"); do { MOZ_CrashSequence(__null, 2073); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2074 MOZ_ASSERT_IF(!MediaEngineSource::IsAudio(aAudioInputType),do { if (!MediaEngineSource::IsAudio(aAudioInputType)) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(aAudioInputType == dom::MediaSourceEnum::Other)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aAudioInputType == dom::MediaSourceEnum::Other))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aAudioInputType == dom::MediaSourceEnum::Other"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2075); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aAudioInputType == dom::MediaSourceEnum::Other"
")"); do { MOZ_CrashSequence(__null, 2075); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2075 aAudioInputType == dom::MediaSourceEnum::Other)do { if (!MediaEngineSource::IsAudio(aAudioInputType)) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(aAudioInputType == dom::MediaSourceEnum::Other)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aAudioInputType == dom::MediaSourceEnum::Other))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aAudioInputType == dom::MediaSourceEnum::Other"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2075); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aAudioInputType == dom::MediaSourceEnum::Other"
")"); do { MOZ_CrashSequence(__null, 2075); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2076 const bool forceFakes = aFlags.contains(EnumerationFlag::ForceFakes);
2077 const bool fakeByPref = Preferences::GetBool("media.navigator.streams.fake");
2078 Maybe<VideoDeviceEnumerationParams> videoParams;
2079 Maybe<DeviceEnumerationParams> audioParams;
2080 nsAutoCString audioDev;
2081 bool audioDevRead = false;
2082 constexpr const char* VIDEO_DEV_NAME = "media.video_loopback_dev";
2083 constexpr const char* AUDIO_DEV_NAME = "media.audio_loopback_dev";
2084 const auto ensureDev = [](const char* aPref, nsAutoCString* aLoopDev,
2085 bool* aPrefRead) {
2086 if (aPrefRead) {
2087 if (*aPrefRead) {
2088 return;
2089 }
2090 *aPrefRead = true;
2091 }
2092
2093 if (NS_FAILED(Preferences::GetCString(aPref, *aLoopDev))((bool)(__builtin_expect(!!(NS_FAILED_impl(Preferences::GetCString
(aPref, *aLoopDev))), 0)))
) {
2094 // Ensure we fall back to an empty string if reading the pref failed.
2095 aLoopDev->SetIsVoid(true);
2096 }
2097 };
2098 if (MediaEngineSource::IsVideo(aVideoInputType)) {
2099 nsAutoCString videoDev;
2100 DeviceType type = DeviceType::Real;
2101 if (aVideoInputType == MediaSourceEnum::Camera) {
2102 // Fake and loopback devices are supported for only Camera.
2103 if (forceFakes) {
2104 type = DeviceType::Fake;
2105 } else {
2106 ensureDev(VIDEO_DEV_NAME, &videoDev, nullptr);
2107 // Loopback prefs take precedence over fake prefs
2108 if (fakeByPref && videoDev.IsEmpty()) {
2109 type = DeviceType::Fake;
2110 } else {
2111 // For groupId correlation we need the audio device name.
2112 ensureDev(AUDIO_DEV_NAME, &audioDev, &audioDevRead);
2113 }
2114 }
2115 }
2116 videoParams = Some(VideoDeviceEnumerationParams(aVideoInputType, type,
2117 videoDev, audioDev));
2118 }
2119 if (MediaEngineSource::IsAudio(aAudioInputType)) {
2120 nsAutoCString realAudioDev;
2121 DeviceType type = DeviceType::Real;
2122 if (aAudioInputType == MediaSourceEnum::Microphone) {
2123 // Fake and loopback devices are supported for only Microphone.
2124 if (forceFakes) {
2125 type = DeviceType::Fake;
2126 } else {
2127 ensureDev(AUDIO_DEV_NAME, &audioDev, &audioDevRead);
2128 // Loopback prefs take precedence over fake prefs
2129 if (fakeByPref && audioDev.IsEmpty()) {
2130 type = DeviceType::Fake;
2131 } else {
2132 realAudioDev = audioDev;
2133 }
2134 }
2135 }
2136 audioParams =
2137 Some(DeviceEnumerationParams(aAudioInputType, type, realAudioDev));
2138 }
2139 return EnumerationParams(aFlags, videoParams, audioParams);
2140}
2141
2142RefPtr<DeviceSetPromise>
2143MediaManager::MaybeRequestPermissionAndEnumerateRawDevices(
2144 EnumerationParams aParams) {
2145 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/MediaManager.cpp", 2145); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2145); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2146 MOZ_ASSERT(aParams.mVideo.isSome() || aParams.mAudio.isSome() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParams.mVideo.isSome() || aParams.mAudio.isSome() ||
aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aParams.mVideo.isSome() || aParams.mAudio.isSome() ||
aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2147); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)"
")"); do { MOZ_CrashSequence(__null, 2147); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2147 aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParams.mVideo.isSome() || aParams.mAudio.isSome() ||
aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aParams.mVideo.isSome() || aParams.mAudio.isSome() ||
aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2147); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)"
")"); do { MOZ_CrashSequence(__null, 2147); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2148
2149 LOG("%s: aVideoInputType=%" PRIu8"u" ", aAudioInputType=%" PRIu8"u", __func__,
2150 static_cast<uint8_t>(aParams.VideoInputType()),
2151 static_cast<uint8_t>(aParams.AudioInputType()));
2152
2153 if (sHasMainThreadShutdown) {
2154 // The media thread is no longer available but the result will not be
2155 // observable.
2156 return DeviceSetPromise::CreateAndResolve(
2157 new MediaDeviceSetRefCnt(),
2158 "MaybeRequestPermissionAndEnumerateRawDevices: sync shutdown");
2159 }
2160
2161 const bool hasVideo = aParams.mVideo.isSome();
2162 const bool hasAudio = aParams.mAudio.isSome();
2163 const bool hasAudioOutput =
2164 aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs);
2165 const bool hasFakeCams = aParams.HasFakeCams();
2166 const bool hasFakeMics = aParams.HasFakeMics();
2167 // True if at least one of video input or audio input is a real device
2168 // or there is audio output.
2169 const bool realDeviceRequested = (!hasFakeCams && hasVideo) ||
2170 (!hasFakeMics && hasAudio) || hasAudioOutput;
2171
2172 using NativePromise =
2173 MozPromise<CamerasAccessStatus, mozilla::ipc::ResponseRejectReason,
2174 /* IsExclusive = */ true>;
2175 RefPtr<NativePromise> deviceAccessPromise;
2176 if (realDeviceRequested &&
2177 aParams.mFlags.contains(EnumerationFlag::AllowPermissionRequest) &&
2178 Preferences::GetBool("media.navigator.permission.device", false)) {
2179 // Need to ask permission to retrieve list of all devices;
2180 // notify frontend observer and wait for callback notification to post
2181 // task.
2182 const char16_t* const type =
2183 (aParams.VideoInputType() != MediaSourceEnum::Camera) ? u"audio"
2184 : (aParams.AudioInputType() != MediaSourceEnum::Microphone) ? u"video"
2185 : u"all";
2186 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
2187 DeviceAccessRequestPromiseHolderWithFallback deviceAccessPromiseHolder;
2188 deviceAccessPromise = deviceAccessPromiseHolder.Ensure(__func__);
2189 RefPtr task = NS_NewRunnableFunction(
2190 __func__, [holder = std::move(deviceAccessPromiseHolder)]() mutable {
2191 holder.Resolve(CamerasAccessStatus::Granted,
2192 "getUserMedia:got-device-permission");
2193 });
2194 obs->NotifyObservers(static_cast<nsIRunnable*>(task),
2195 "getUserMedia:ask-device-permission", type);
2196 } else if (realDeviceRequested && hasVideo &&
2197 aParams.VideoInputType() == MediaSourceEnum::Camera) {
2198 ipc::PBackgroundChild* backgroundChild =
2199 ipc::BackgroundChild::GetOrCreateForCurrentThread();
2200 deviceAccessPromise = backgroundChild->SendRequestCameraAccess(
2201 aParams.mFlags.contains(EnumerationFlag::AllowPermissionRequest));
2202 }
2203
2204 if (!deviceAccessPromise) {
2205 // No device access request needed. We can proceed directly, but we still
2206 // need to update camera availability, because the camera engine is always
2207 // created together with the WebRTC backend, which is done because
2208 // devicechange events must work before prompting in cases where persistent
2209 // permission has already been given. Making a request to camera access not
2210 // allowing a permission request does exactly what we need in this case.
2211 ipc::PBackgroundChild* backgroundChild =
2212 ipc::BackgroundChild::GetOrCreateForCurrentThread();
2213 deviceAccessPromise = backgroundChild->SendRequestCameraAccess(false);
2214 }
2215
2216 return deviceAccessPromise->Then(
2217 GetCurrentSerialEventTarget(), __func__,
2218 [this, self = RefPtr(this), aParams = std::move(aParams)](
2219 NativePromise::ResolveOrRejectValue&& aValue) mutable {
2220 if (sHasMainThreadShutdown) {
2221 return DeviceSetPromise::CreateAndResolve(
2222 new MediaDeviceSetRefCnt(),
2223 "MaybeRequestPermissionAndEnumerateRawDevices: async shutdown");
2224 }
2225
2226 if (aValue.IsReject()) {
2227 // IPC failure probably means we're in shutdown. Resolve with
2228 // an empty set, so that callers do not need to handle rejection.
2229 return DeviceSetPromise::CreateAndResolve(
2230 new MediaDeviceSetRefCnt(),
2231 "MaybeRequestPermissionAndEnumerateRawDevices: ipc failure");
2232 }
2233
2234 if (auto v = aValue.ResolveValue();
2235 v == CamerasAccessStatus::Error ||
2236 v == CamerasAccessStatus::Rejected) {
2237 LOG("Request to camera access %s",
2238 v == CamerasAccessStatus::Rejected ? "was rejected" : "failed");
2239 if (v == CamerasAccessStatus::Error) {
2240 NS_WARNING("Failed to request camera access")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to request camera access"
, nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp", 2240
)
;
2241 }
2242 return DeviceSetPromise::CreateAndReject(
2243 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError),
2244 "MaybeRequestPermissionAndEnumerateRawDevices: camera access "
2245 "rejected");
2246 }
2247
2248 if (aParams.VideoInputType() == MediaSourceEnum::Camera &&
2249 aParams.mFlags.contains(EnumerationFlag::AllowPermissionRequest) &&
2250 aValue.ResolveValue() == CamerasAccessStatus::Granted) {
2251 EnsureNoPlaceholdersInDeviceCache();
2252 }
2253
2254 // We have to nest this, unfortunately, since we have no guarantees that
2255 // mMediaThread is alive. If we'd reject due to shutdown above, and have
2256 // the below async operation in a Then handler on the media thread the
2257 // Then handler would fail to dispatch and trip an assert on
2258 // destruction, for instance.
2259 return InvokeAsync(
2260 mMediaThread, __func__, [aParams = std::move(aParams)]() mutable {
2261 return DeviceSetPromise::CreateAndResolve(
2262 EnumerateRawDevices(std::move(aParams)),
2263 "MaybeRequestPermissionAndEnumerateRawDevices: success");
2264 });
2265 });
2266}
2267
2268/**
2269 * EnumerateRawDevices - Enumerate a list of audio & video devices that
2270 * satisfy passed-in constraints. List contains raw id's.
2271 */
2272
2273/* static */ RefPtr<MediaManager::MediaDeviceSetRefCnt>
2274MediaManager::EnumerateRawDevices(EnumerationParams aParams) {
2275 MOZ_ASSERT(IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2275); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 2275); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2276 // Only enumerate what's asked for, and only fake cams and mics.
2277 RefPtr<MediaEngine> fakeBackend, realBackend;
2278 if (aParams.HasFakeCams() || aParams.HasFakeMics()) {
2279 fakeBackend = new MediaEngineFake();
2280 }
2281 if (aParams.RealDeviceRequested()) {
2282 MediaManager* manager = MediaManager::GetIfExists();
2283 MOZ_RELEASE_ASSERT(manager, "Must exist while media thread is alive")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(manager)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(manager))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("manager" " (" "Must exist while media thread is alive"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 2283)
; AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "manager" ") ("
"Must exist while media thread is alive" ")"); do { MOZ_CrashSequence
(__null, 2283); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2284 realBackend = manager->GetBackend();
2285 }
2286
2287 RefPtr<MediaEngine> videoBackend;
2288 RefPtr<MediaEngine> audioBackend;
2289 Maybe<MediaDeviceSet> micsOfVideoBackend;
2290 Maybe<MediaDeviceSet> speakers;
2291 RefPtr devices = new MediaDeviceSetRefCnt();
2292
2293 // Enumerate microphones first, then cameras, then speakers, since
2294 // the enumerateDevices() algorithm expects them listed in that order.
2295 if (const auto& audio = aParams.mAudio; audio.isSome()) {
2296 audioBackend = aParams.HasFakeMics() ? fakeBackend : realBackend;
2297 MediaDeviceSet audios;
2298 LOG("EnumerateRawDevices: Getting audio sources with %s backend",
2299 audioBackend == fakeBackend ? "fake" : "real");
2300 GetMediaDevices(audioBackend, audio->mInputType, audios,
2301 audio->mForcedDeviceName.get());
2302 if (audio->mInputType == MediaSourceEnum::Microphone &&
2303 audioBackend == videoBackend) {
2304 micsOfVideoBackend.emplace();
2305 micsOfVideoBackend->AppendElements(audios);
2306 }
2307 devices->AppendElements(std::move(audios));
2308 }
2309 if (const auto& video = aParams.mVideo; video.isSome()) {
2310 videoBackend = aParams.HasFakeCams() ? fakeBackend : realBackend;
2311 MediaDeviceSet videos;
2312 LOG("EnumerateRawDevices: Getting video sources with %s backend",
2313 videoBackend == fakeBackend ? "fake" : "real");
2314 GetMediaDevices(videoBackend, video->mInputType, videos,
2315 video->mForcedDeviceName.get());
2316 devices->AppendElements(std::move(videos));
2317 }
2318 if (aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)) {
2319 MediaDeviceSet outputs;
2320 MOZ_ASSERT(realBackend)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(realBackend)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(realBackend))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("realBackend", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2320); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realBackend"
")"); do { MOZ_CrashSequence(__null, 2320); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2321 realBackend->EnumerateDevices(MediaSourceEnum::Other,
2322 MediaSinkEnum::Speaker, &outputs);
2323 speakers = Some(MediaDeviceSet());
2324 speakers->AppendElements(outputs);
2325 devices->AppendElements(std::move(outputs));
2326 }
2327 if (aParams.VideoInputType() == MediaSourceEnum::Camera) {
2328 MediaDeviceSet audios;
2329 LOG("EnumerateRawDevices: Getting audio sources with %s backend for "
2330 "groupId correlation",
2331 videoBackend == fakeBackend ? "fake" : "real");
2332 // We need to correlate cameras with audio groupIds. We use the backend of
2333 // the camera to always do correlation on devices in the same scope. If we
2334 // don't do this, video-only getUserMedia will not apply groupId constraints
2335 // to the same set of groupIds as gets returned by enumerateDevices.
2336 if (micsOfVideoBackend.isSome()) {
2337 // Microphones from the same backend used for the cameras have
2338 // already been enumerated. Avoid doing it again.
2339 MOZ_ASSERT(aParams.mVideo->mForcedMicrophoneName ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParams.mVideo->mForcedMicrophoneName == aParams.
mAudio->mForcedDeviceName)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParams.mVideo->mForcedMicrophoneName
== aParams.mAudio->mForcedDeviceName))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2340); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName"
")"); do { MOZ_CrashSequence(__null, 2340); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2340 aParams.mAudio->mForcedDeviceName)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParams.mVideo->mForcedMicrophoneName == aParams.
mAudio->mForcedDeviceName)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParams.mVideo->mForcedMicrophoneName
== aParams.mAudio->mForcedDeviceName))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2340); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName"
")"); do { MOZ_CrashSequence(__null, 2340); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2341 audios.AppendElements(micsOfVideoBackend.extract());
2342 } else {
2343 GetMediaDevices(videoBackend, MediaSourceEnum::Microphone, audios,
2344 aParams.mVideo->mForcedMicrophoneName.get());
2345 }
2346 if (videoBackend == realBackend) {
2347 // When using the real backend for video, there could also be
2348 // speakers to correlate with. There are no fake speakers.
2349 if (speakers.isSome()) {
2350 // Speakers have already been enumerated. Avoid doing it again.
2351 audios.AppendElements(speakers.extract());
2352 } else {
2353 realBackend->EnumerateDevices(MediaSourceEnum::Other,
2354 MediaSinkEnum::Speaker, &audios);
2355 }
2356 }
2357 GuessVideoDeviceGroupIDs(*devices, audios);
2358 }
2359
2360 return devices;
2361}
2362
2363RefPtr<ConstDeviceSetPromise> MediaManager::GetPhysicalDevices() {
2364 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/MediaManager.cpp", 2364); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2364); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2365 if (mPhysicalDevices) {
2366 return ConstDeviceSetPromise::CreateAndResolve(mPhysicalDevices, __func__);
2367 }
2368 if (mPendingDevicesPromises) {
2369 // Enumeration is already in progress.
2370 return mPendingDevicesPromises->AppendElement()->Ensure(__func__);
2371 }
2372 mPendingDevicesPromises =
2373 new Refcountable<nsTArray<MozPromiseHolder<ConstDeviceSetPromise>>>;
2374 MaybeRequestPermissionAndEnumerateRawDevices(
2375 CreateEnumerationParams(MediaSourceEnum::Camera,
2376 MediaSourceEnum::Microphone,
2377 EnumerationFlag::EnumerateAudioOutputs))
2378 ->Then(
2379 GetCurrentSerialEventTarget(), __func__,
2380 [self = RefPtr(this), this, promises = mPendingDevicesPromises](
2381 RefPtr<MediaDeviceSetRefCnt> aDevices) mutable {
2382 for (auto& promiseHolder : *promises) {
2383 promiseHolder.Resolve(aDevices, __func__);
2384 }
2385 // mPendingDevicesPromises may have changed if devices have changed.
2386 if (promises == mPendingDevicesPromises) {
2387 mPendingDevicesPromises = nullptr;
2388 mPhysicalDevices = std::move(aDevices);
2389 }
2390 },
2391 [](RefPtr<MediaMgrError>&& reason) {
2392 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"MaybeRequestPermissionAndEnumerateRawDevices does not reject"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 2393)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"MaybeRequestPermissionAndEnumerateRawDevices does not reject"
")"); do { MOZ_CrashSequence(__null, 2393); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2393 "MaybeRequestPermissionAndEnumerateRawDevices does not reject")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: "
"MaybeRequestPermissionAndEnumerateRawDevices does not reject"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 2393)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"MaybeRequestPermissionAndEnumerateRawDevices does not reject"
")"); do { MOZ_CrashSequence(__null, 2393); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2394 });
2395
2396 return mPendingDevicesPromises->AppendElement()->Ensure(__func__);
2397}
2398
2399MediaManager::MediaManager(already_AddRefed<TaskQueue> aMediaThread)
2400 : mMediaThread(aMediaThread), mBackend(nullptr) {
2401 mPrefs.mFreq = 1000; // 1KHz test tone
2402 mPrefs.mWidth = 0; // adaptive default
2403 mPrefs.mHeight = 0; // adaptive default
2404 mPrefs.mResizeModeEnabled = false;
2405 mPrefs.mResizeMode = VideoResizeModeEnum::None;
2406 mPrefs.mFPS = MediaEnginePrefs::DEFAULT_VIDEO_FPS;
2407 mPrefs.mUsePlatformProcessing = false;
2408 mPrefs.mAecOn = false;
2409 mPrefs.mUseAecMobile = false;
2410 mPrefs.mAgcOn = false;
2411 mPrefs.mHPFOn = false;
2412 mPrefs.mNoiseOn = false;
2413 mPrefs.mTransientOn = false;
2414 mPrefs.mAgc2Forced = false;
2415 mPrefs.mExpectDrift = -1; // auto
2416#ifdef MOZ_WEBRTC1
2417 mPrefs.mAgc =
2418 webrtc::AudioProcessing::Config::GainController1::Mode::kAdaptiveDigital;
2419 mPrefs.mNoise =
2420 webrtc::AudioProcessing::Config::NoiseSuppression::Level::kModerate;
2421#else
2422 mPrefs.mAgc = 0;
2423 mPrefs.mNoise = 0;
2424#endif
2425 mPrefs.mChannels = 0; // max channels default
2426 nsresult rv;
2427 nsCOMPtr<nsIPrefService> prefs =
2428 do_GetService("@mozilla.org/preferences-service;1", &rv);
2429 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2430 nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
2431 if (branch) {
2432 GetPrefs(branch, nullptr);
2433 }
2434 }
2435}
2436
2437NS_IMPL_ISUPPORTS(MediaManager, nsIMediaManagerService, nsIMemoryReporter,MozExternalRefCountType MediaManager::AddRef(void) { static_assert
(!std::is_destructible_v<MediaManager>, "Reference-counted class "
"MediaManager" " 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/MediaManager.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 2438
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2438); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("MediaManager" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("MediaManager"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
MediaManager::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/MediaManager.cpp", 2438)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 2438
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2438); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("MediaManager" " not thread-safe"); const char
* const nametmp = "MediaManager"; nsrefcnt count = --mRefCnt;
NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; } nsresult
MediaManager::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/MediaManager.cpp", 2438); MOZ_PretendNoReturn
(); } } while (0); nsresult rv = NS_ERROR_FAILURE; static_assert
(3 > 0, "Need more arguments to NS_INTERFACE_TABLE"); static
const QITableEntry table[] = { {&mozilla::detail::kImplementedIID
<MediaManager, nsIMediaManagerService>, int32_t( reinterpret_cast
<char*>(static_cast<nsIMediaManagerService*>((MediaManager
*)0x1000)) - reinterpret_cast<char*>((MediaManager*)0x1000
))}, {&mozilla::detail::kImplementedIID<MediaManager, nsIMemoryReporter
>, int32_t( reinterpret_cast<char*>(static_cast<nsIMemoryReporter
*>((MediaManager*)0x1000)) - reinterpret_cast<char*>
((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID
<MediaManager, nsIObserver>, int32_t( reinterpret_cast<
char*>(static_cast<nsIObserver*>((MediaManager*)0x1000
)) - reinterpret_cast<char*>((MediaManager*)0x1000))}, {
&mozilla::detail::kImplementedIID<MediaManager, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIMediaManagerService*>((MediaManager
*)0x1000))) - reinterpret_cast<char*>((MediaManager*)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; }
2438 nsIObserver)MozExternalRefCountType MediaManager::AddRef(void) { static_assert
(!std::is_destructible_v<MediaManager>, "Reference-counted class "
"MediaManager" " 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/MediaManager.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 2438
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2438); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("MediaManager" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("MediaManager"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
MediaManager::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/MediaManager.cpp", 2438)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 2438
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2438); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("MediaManager" " not thread-safe"); const char
* const nametmp = "MediaManager"; nsrefcnt count = --mRefCnt;
NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; } nsresult
MediaManager::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/MediaManager.cpp", 2438); MOZ_PretendNoReturn
(); } } while (0); nsresult rv = NS_ERROR_FAILURE; static_assert
(3 > 0, "Need more arguments to NS_INTERFACE_TABLE"); static
const QITableEntry table[] = { {&mozilla::detail::kImplementedIID
<MediaManager, nsIMediaManagerService>, int32_t( reinterpret_cast
<char*>(static_cast<nsIMediaManagerService*>((MediaManager
*)0x1000)) - reinterpret_cast<char*>((MediaManager*)0x1000
))}, {&mozilla::detail::kImplementedIID<MediaManager, nsIMemoryReporter
>, int32_t( reinterpret_cast<char*>(static_cast<nsIMemoryReporter
*>((MediaManager*)0x1000)) - reinterpret_cast<char*>
((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID
<MediaManager, nsIObserver>, int32_t( reinterpret_cast<
char*>(static_cast<nsIObserver*>((MediaManager*)0x1000
)) - reinterpret_cast<char*>((MediaManager*)0x1000))}, {
&mozilla::detail::kImplementedIID<MediaManager, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIMediaManagerService*>((MediaManager
*)0x1000))) - reinterpret_cast<char*>((MediaManager*)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; }
2439
2440/* static */
2441StaticRefPtr<MediaManager> MediaManager::sSingleton;
2442
2443#ifdef DEBUG1
2444/* static */
2445bool MediaManager::IsInMediaThread() {
2446 return sSingleton && sSingleton->mMediaThread->IsOnCurrentThread();
2447}
2448#endif
2449
2450template <typename Function>
2451static void ForeachObservedPref(const Function& aFunction) {
2452 aFunction("media.navigator.video.default_width"_ns);
2453 aFunction("media.navigator.video.default_height"_ns);
2454 aFunction("media.navigator.video.default_fps"_ns);
2455 aFunction("media.navigator.audio.fake_frequency"_ns);
2456 aFunction("media.audio_loopback_dev"_ns);
2457 aFunction("media.video_loopback_dev"_ns);
2458 aFunction("media.getusermedia.fake-camera-name"_ns);
2459#ifdef MOZ_WEBRTC1
2460 aFunction("media.navigator.video.resize_mode.enabled"_ns);
2461 aFunction("media.navigator.video.default_resize_mode"_ns);
2462 aFunction("media.getusermedia.audio.processing.aec.enabled"_ns);
2463 aFunction("media.getusermedia.audio.processing.aec"_ns);
2464 aFunction("media.getusermedia.audio.processing.agc.enabled"_ns);
2465 aFunction("media.getusermedia.audio.processing.agc"_ns);
2466 aFunction("media.getusermedia.audio.processing.hpf.enabled"_ns);
2467 aFunction("media.getusermedia.audio.processing.noise.enabled"_ns);
2468 aFunction("media.getusermedia.audio.processing.noise"_ns);
2469 aFunction("media.getusermedia.audio.max_channels"_ns);
2470 aFunction("media.navigator.streams.fake"_ns);
2471#endif
2472}
2473
2474// NOTE: never NS_DispatchAndSpinEventLoopUntilComplete to the MediaManager
2475// thread from the MainThread, as we NS_DispatchAndSpinEventLoopUntilComplete to
2476// MainThread from MediaManager thread.
2477
2478// Guaranteed never to return nullptr.
2479/* static */
2480MediaManager* MediaManager::Get() {
2481 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/MediaManager.cpp", 2481); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2481); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2482
2483 if (!sSingleton) {
2484 static int timesCreated = 0;
2485 timesCreated++;
2486 MOZ_RELEASE_ASSERT(timesCreated == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(timesCreated == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(timesCreated == 1))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("timesCreated == 1"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2486); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "timesCreated == 1" ")"); do { MOZ_CrashSequence
(__null, 2486); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2487
2488 constexpr bool kSupportsTailDispatch = false;
2489 RefPtr<TaskQueue> mediaThread =
2490#ifdef MOZ_WEBRTC1
2491 CreateWebrtcTaskQueueWrapper(
2492 GetMediaThreadPool(MediaThreadType::SUPERVISOR), "MediaManager"_ns,
2493 kSupportsTailDispatch);
2494#else
2495 TaskQueue::Create(GetMediaThreadPool(MediaThreadType::SUPERVISOR),
2496 "MediaManager", kSupportsTailDispatch);
2497#endif
2498 LOG("New Media thread for gum");
2499
2500 sSingleton = new MediaManager(mediaThread.forget());
2501
2502 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
2503 if (obs) {
2504 obs->AddObserver(sSingleton, "last-pb-context-exited", false);
2505 obs->AddObserver(sSingleton, "getUserMedia:got-device-permission", false);
2506 obs->AddObserver(sSingleton, "getUserMedia:privileged:allow", false);
2507 obs->AddObserver(sSingleton, "getUserMedia:response:allow", false);
2508 obs->AddObserver(sSingleton, "getUserMedia:response:deny", false);
2509 obs->AddObserver(sSingleton, "getUserMedia:response:noOSPermission",
2510 false);
2511 obs->AddObserver(sSingleton, "getUserMedia:revoke", false);
2512 obs->AddObserver(sSingleton, "getUserMedia:muteVideo", false);
2513 obs->AddObserver(sSingleton, "getUserMedia:unmuteVideo", false);
2514 obs->AddObserver(sSingleton, "getUserMedia:muteAudio", false);
2515 obs->AddObserver(sSingleton, "getUserMedia:unmuteAudio", false);
2516 obs->AddObserver(sSingleton, "application-background", false);
2517 obs->AddObserver(sSingleton, "application-foreground", false);
2518 }
2519 // else MediaManager won't work properly and will leak (see bug 837874)
2520 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1");
2521 if (prefs) {
2522 ForeachObservedPref([&](const nsLiteralCString& aPrefName) {
2523 prefs->AddObserver(aPrefName, sSingleton, false);
2524 });
2525 }
2526 RegisterStrongMemoryReporter(sSingleton);
2527
2528 // Prepare async shutdown
2529
2530 class Blocker : public media::ShutdownBlocker {
2531 public:
2532 Blocker()
2533 : media::ShutdownBlocker(
2534 u"Media shutdown: blocking on media thread"_ns) {}
2535
2536 NS_IMETHODvirtual nsresult BlockShutdown(nsIAsyncShutdownClient*) override {
2537 MOZ_RELEASE_ASSERT(MediaManager::GetIfExists())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::GetIfExists())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::GetIfExists())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaManager::GetIfExists()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2537); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "MediaManager::GetIfExists()" ")");
do { MOZ_CrashSequence(__null, 2537); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2538 MediaManager::GetIfExists()->Shutdown();
2539 return NS_OK;
2540 }
2541 };
2542
2543 sSingleton->mShutdownBlocker = new Blocker();
2544 nsresult rv = media::MustGetShutdownBarrier()->AddBlocker(
2545 sSingleton->mShutdownBlocker, NS_LITERAL_STRING_FROM_CSTRING(__FILE__)static_cast<const nsLiteralString&>( nsLiteralString
(u"" "/root/firefox-clang/dom/media/MediaManager.cpp"))
,
2546 __LINE__2546, u""_ns);
2547 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2547); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2548 }
2549 return sSingleton;
2550}
2551
2552/* static */
2553MediaManager* MediaManager::GetIfExists() {
2554 MOZ_ASSERT(NS_IsMainThread() || IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread() || IsInMediaThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(NS_IsMainThread() || IsInMediaThread()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("NS_IsMainThread() || IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2554); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread() || IsInMediaThread()" ")"
); do { MOZ_CrashSequence(__null, 2554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2555 return sSingleton;
2556}
2557
2558/* static */
2559already_AddRefed<MediaManager> MediaManager::GetInstance() {
2560 // so we can have non-refcounted getters
2561 RefPtr<MediaManager> service = MediaManager::Get();
2562 return service.forget();
2563}
2564
2565media::Parent<media::NonE10s>* MediaManager::GetNonE10sParent() {
2566 if (!mNonE10sParent) {
2567 mNonE10sParent = new media::Parent<media::NonE10s>();
2568 }
2569 return mNonE10sParent;
2570}
2571
2572/* static */
2573void MediaManager::Dispatch(already_AddRefed<Runnable> task) {
2574 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/MediaManager.cpp", 2574); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2574); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2575 if (sHasMainThreadShutdown) {
2576 // Can't safely delete task here since it may have items with specific
2577 // thread-release requirements.
2578 // XXXkhuey well then who is supposed to delete it?! We don't signal
2579 // that we failed ...
2580 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2580); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence
(__null, 2580); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
2581 return;
2582 }
2583 NS_ASSERTION(Get(), "MediaManager singleton?")do { if (!(Get())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "MediaManager singleton?"
, "Get()", "/root/firefox-clang/dom/media/MediaManager.cpp", 2583
); MOZ_PretendNoReturn(); } } while (0)
;
2584 NS_ASSERTION(Get()->mMediaThread, "No thread yet")do { if (!(Get()->mMediaThread)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "No thread yet", "Get()->mMediaThread", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2584); MOZ_PretendNoReturn(); } } while (0)
;
2585 MOZ_ALWAYS_SUCCEEDS(Get()->mMediaThread->Dispatch(std::move(task)))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(Get()->mMediaThread->Dispatch(std::move(task)))), 1)))
), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(Get()->mMediaThread->Dispatch(std::move(task)))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2585); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(Get()->mMediaThread->Dispatch(std::move(task)))"
")"); do { MOZ_CrashSequence(__null, 2585); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2586}
2587
2588template <typename MozPromiseType, typename FunctionType>
2589/* static */
2590RefPtr<MozPromiseType> MediaManager::Dispatch(StaticString aName,
2591 FunctionType&& aFunction) {
2592 MozPromiseHolder<MozPromiseType> holder;
2593 RefPtr<MozPromiseType> promise = holder.Ensure(aName);
2594 MediaManager::Dispatch(NS_NewRunnableFunction(
2595 aName, [h = std::move(holder), func = std::forward<FunctionType>(
2596 aFunction)]() mutable { func(h); }));
2597 return promise;
2598}
2599
2600/* static */
2601nsresult MediaManager::NotifyRecordingStatusChange(
2602 nsPIDOMWindowInner* aWindow) {
2603 NS_ENSURE_ARG(aWindow)do { if ((__builtin_expect(!!(!(aWindow)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWindow" ") failed", nullptr
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2603); return
NS_ERROR_INVALID_ARG; } } while (false)
;
2604
2605 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
2606 if (!obs) {
2607 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Could not get the Observer service for GetUserMedia recording "
"notification.", nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2609)
2608 "Could not get the Observer service for GetUserMedia recording "NS_DebugBreak(NS_DEBUG_WARNING, "Could not get the Observer service for GetUserMedia recording "
"notification.", nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2609)
2609 "notification.")NS_DebugBreak(NS_DEBUG_WARNING, "Could not get the Observer service for GetUserMedia recording "
"notification.", nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2609)
;
2610 return NS_ERROR_FAILURE;
2611 }
2612
2613 auto props = MakeRefPtr<nsHashPropertyBag>();
2614
2615 nsCString pageURL;
2616 nsCOMPtr<nsIURI> docURI = aWindow->GetDocumentURI();
2617 NS_ENSURE_TRUE(docURI, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(docURI)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "docURI" ") failed", nullptr
, "/root/firefox-clang/dom/media/MediaManager.cpp", 2617); return
NS_ERROR_FAILURE; } } while (false)
;
2618
2619 nsresult rv = docURI->GetSpec(pageURL);
2620 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2620); return rv; } } while (false)
;
2621
2622 NS_ConvertUTF8toUTF16 requestURL(pageURL);
2623
2624 props->SetPropertyAsAString(u"requestURL"_ns, requestURL);
2625 props->SetPropertyAsInterface(u"window"_ns, aWindow);
2626
2627 obs->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
2628 "recording-device-events", nullptr);
2629 LOG("Sent recording-device-events for url '%s'", pageURL.get());
2630
2631 return NS_OK;
2632}
2633
2634void MediaManager::DeviceListChanged() {
2635 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/MediaManager.cpp", 2635); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2635); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2636 if (sHasMainThreadShutdown) {
2637 return;
2638 }
2639 // Invalidate immediately to provide an up-to-date device list for future
2640 // enumerations on platforms with sane device-list-changed events.
2641 InvalidateDeviceCache();
2642
2643 // Wait 200 ms, because
2644 // A) on some Windows machines, if we call EnumerateRawDevices immediately
2645 // after receiving devicechange event, we'd get an outdated devices list.
2646 // B) Waiting helps coalesce multiple calls on us into one, which can happen
2647 // if a device with both audio input and output is attached or removed.
2648 // We want to react & fire a devicechange event only once in that case.
2649
2650 // The wait is extended if another hardware device-list-changed notification
2651 // is received to provide the full 200ms for EnumerateRawDevices().
2652 if (mDeviceChangeTimer) {
2653 mDeviceChangeTimer->Cancel();
2654 } else {
2655 mDeviceChangeTimer = MakeRefPtr<MediaTimer<TimeStamp>>();
2656 }
2657 // However, if this would cause a delay of over 1000ms in handling the
2658 // oldest unhandled event, then respond now and set the timer to run
2659 // EnumerateRawDevices() again in 200ms.
2660 auto now = TimeStamp::NowLoRes();
2661 auto enumerateDelay = TimeDuration::FromMilliseconds(200);
2662 auto coalescenceLimit = TimeDuration::FromMilliseconds(1000) - enumerateDelay;
2663 if (!mUnhandledDeviceChangeTime) {
2664 mUnhandledDeviceChangeTime = now;
2665 } else if (now - mUnhandledDeviceChangeTime > coalescenceLimit) {
2666 HandleDeviceListChanged();
2667 mUnhandledDeviceChangeTime = now;
2668 }
2669 RefPtr<MediaManager> self = this;
2670 mDeviceChangeTimer->WaitFor(enumerateDelay, __func__)
2671 ->Then(
2672 GetCurrentSerialEventTarget(), __func__,
2673 [self, this] {
2674 // Invalidate again for the sake of platforms with inconsistent
2675 // timing between device-list-changed notification and enumeration.
2676 InvalidateDeviceCache();
2677
2678 mUnhandledDeviceChangeTime = TimeStamp();
2679 HandleDeviceListChanged();
2680 },
2681 [] { /* Timer was canceled by us, or we're in shutdown. */ });
2682}
2683
2684void MediaManager::EnsureNoPlaceholdersInDeviceCache() {
2685 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/MediaManager.cpp", 2685); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2685); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2686
2687 if (mPhysicalDevices) {
2688 // Invalidate the list if there is a placeholder
2689 for (const auto& device : *mPhysicalDevices) {
2690 if (device->mIsPlaceholder) {
2691 InvalidateDeviceCache();
2692 break;
2693 }
2694 }
2695 }
2696}
2697
2698void MediaManager::InvalidateDeviceCache() {
2699 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/MediaManager.cpp", 2699); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2699); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2700
2701 mPhysicalDevices = nullptr;
2702 // Disconnect any in-progress enumeration, which may now be out of date,
2703 // from updating mPhysicalDevices or resolving future device request
2704 // promises.
2705 mPendingDevicesPromises = nullptr;
2706}
2707
2708void MediaManager::HandleDeviceListChanged() {
2709 mDeviceListChangeEvent.Notify();
2710
2711 GetPhysicalDevices()->Then(
2712 GetCurrentSerialEventTarget(), __func__,
2713 [self = RefPtr(this), this](RefPtr<const MediaDeviceSetRefCnt> aDevices) {
2714 if (!MediaManager::GetIfExists()) {
2715 return;
2716 }
2717
2718 nsTHashSet<nsString> deviceIDs;
2719 for (const auto& device : *aDevices) {
2720 deviceIDs.Insert(device->mRawID);
2721 }
2722 // For any real removed cameras or microphones, notify their
2723 // listeners cleanly that the source has stopped, so JS knows and
2724 // usage indicators update.
2725 // First collect the listeners in an array to stop them after
2726 // iterating the hashtable. The StopRawID() method indirectly
2727 // modifies the mActiveWindows and would assert-crash if the
2728 // iterator were active while the table is being enumerated.
2729 const auto windowListeners = ToArray(mActiveWindows.Values());
2730 for (const RefPtr<GetUserMediaWindowListener>& l : windowListeners) {
2731 const auto activeDevices = l->GetDevices();
2732 for (const RefPtr<LocalMediaDevice>& device : *activeDevices) {
2733 if (device->IsFake()) {
2734 continue;
2735 }
2736 MediaSourceEnum mediaSource = device->GetMediaSource();
2737 if (mediaSource != MediaSourceEnum::Microphone &&
2738 mediaSource != MediaSourceEnum::Camera) {
2739 continue;
2740 }
2741 if (!deviceIDs.Contains(device->RawID())) {
2742 // Device has been removed
2743 l->StopRawID(device->RawID());
2744 }
2745 }
2746 }
2747 },
2748 [](RefPtr<MediaMgrError>&& reason) {
2749 MOZ_ASSERT_UNREACHABLE("EnumerateRawDevices does not reject")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: "
"EnumerateRawDevices does not reject" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "EnumerateRawDevices does not reject"
")"); do { MOZ_CrashSequence(__null, 2749); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2750 });
2751}
2752
2753size_t MediaManager::AddTaskAndGetCount(uint64_t aWindowID,
2754 const nsAString& aCallID,
2755 RefPtr<GetUserMediaTask> aTask) {
2756 // Store the task w/callbacks.
2757 mActiveCallbacks.InsertOrUpdate(aCallID, std::move(aTask));
2758
2759 // Add a WindowID cross-reference so OnNavigation can tear things down
2760 nsTArray<nsString>* const array = mCallIds.GetOrInsertNew(aWindowID);
2761 array->AppendElement(aCallID);
2762
2763 return array->Length();
2764}
2765
2766RefPtr<GetUserMediaTask> MediaManager::TakeGetUserMediaTask(
2767 const nsAString& aCallID) {
2768 RefPtr<GetUserMediaTask> task;
2769 mActiveCallbacks.Remove(aCallID, getter_AddRefs(task));
2770 if (!task) {
2771 return nullptr;
2772 }
2773 nsTArray<nsString>* array;
2774 mCallIds.Get(task->GetWindowID(), &array);
2775 MOZ_ASSERT(array)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(array)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(array))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("array", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "array" ")")
; do { MOZ_CrashSequence(__null, 2775); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2776 array->RemoveElement(aCallID);
2777 return task;
2778}
2779
2780void MediaManager::NotifyAllowed(const nsString& aCallID,
2781 const LocalMediaDeviceSet& aDevices) {
2782 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
2783 nsCOMPtr<nsIMutableArray> devicesCopy = nsArray::Create();
2784 for (const auto& device : aDevices) {
2785 nsresult rv = devicesCopy->AppendElement(device);
2786 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2786)
) {
2787 obs->NotifyObservers(nullptr, "getUserMedia:response:deny",
2788 aCallID.get());
2789 return;
2790 }
2791 }
2792 obs->NotifyObservers(devicesCopy, "getUserMedia:privileged:allow",
2793 aCallID.get());
2794}
2795
2796nsresult MediaManager::GenerateUUID(nsAString& aResult) {
2797 nsresult rv;
2798 nsCOMPtr<nsIUUIDGenerator> uuidgen =
2799 do_GetService("@mozilla.org/uuid-generator;1", &rv);
2800 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2800); return rv; } } while (false)
;
2801
2802 // Generate a call ID.
2803 nsID id;
2804 rv = uuidgen->GenerateUUIDInPlace(&id);
2805 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2805); return rv; } } while (false)
;
2806
2807 char buffer[NSID_LENGTH39];
2808 id.ToProvidedString(buffer);
2809 aResult.Assign(NS_ConvertUTF8toUTF16(buffer));
2810 return NS_OK;
2811}
2812
2813enum class GetUserMediaSecurityState {
2814 Other = 0,
2815 HTTPS = 1,
2816 File = 2,
2817 App = 3,
2818 Localhost = 4,
2819 Loop = 5,
2820 Privileged = 6
2821};
2822
2823/**
2824 * This function is used in getUserMedia when privacy.resistFingerprinting is
2825 * true. Only mediaSource of audio/video constraint will be kept. On mobile
2826 * facing mode is also kept.
2827 */
2828static void ReduceConstraint(
2829 OwningBooleanOrMediaTrackConstraints& aConstraint) {
2830 // Not requesting stream.
2831 if (!MediaManager::IsOn(aConstraint)) {
2832 return;
2833 }
2834
2835 // It looks like {audio: true}, do nothing.
2836 if (!aConstraint.IsMediaTrackConstraints()) {
2837 return;
2838 }
2839
2840 // Keep mediaSource.
2841 Maybe<nsString> mediaSource;
2842 if (aConstraint.GetAsMediaTrackConstraints().mMediaSource.WasPassed()) {
2843 mediaSource =
2844 Some(aConstraint.GetAsMediaTrackConstraints().mMediaSource.Value());
2845 }
2846
2847 Maybe<OwningStringOrStringSequenceOrConstrainDOMStringParameters> facingMode;
2848 if (aConstraint.GetAsMediaTrackConstraints().mFacingMode.WasPassed()) {
2849 facingMode =
2850 Some(aConstraint.GetAsMediaTrackConstraints().mFacingMode.Value());
2851 }
2852
2853 aConstraint.Uninit();
2854 if (mediaSource) {
2855 aConstraint.SetAsMediaTrackConstraints().mMediaSource.Construct(
2856 *mediaSource);
2857 } else {
2858 Unused << aConstraint.SetAsMediaTrackConstraints();
2859 }
2860
2861#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
2862 if (facingMode) {
2863 aConstraint.SetAsMediaTrackConstraints().mFacingMode.Construct(*facingMode);
2864 } else {
2865 Unused << aConstraint.SetAsMediaTrackConstraints();
2866 }
2867#endif
2868}
2869
2870/**
2871 * The entry point for this file. A call from MediaDevices::GetUserMedia
2872 * will end up here. MediaManager is a singleton that is responsible
2873 * for handling all incoming getUserMedia calls from every window.
2874 */
2875RefPtr<MediaManager::StreamPromise> MediaManager::GetUserMedia(
2876 nsPIDOMWindowInner* aWindow,
2877 const MediaStreamConstraints& aConstraintsPassedIn,
2878 CallerType aCallerType) {
2879 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/MediaManager.cpp", 2879); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2879); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2880 MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWindow", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2880); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 2880); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2881 uint64_t windowID = aWindow->WindowID();
2882
2883 MediaStreamConstraints c(aConstraintsPassedIn); // use a modifiable copy
2884
2885 if (sHasMainThreadShutdown) {
2886 return StreamPromise::CreateAndReject(
2887 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError,
2888 "In shutdown"),
2889 __func__);
2890 }
2891
2892 // Determine permissions early (while we still have a stack).
2893
2894 nsIURI* docURI = aWindow->GetDocumentURI();
2895 if (!docURI) {
2896 return StreamPromise::CreateAndReject(
2897 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), __func__);
2898 }
2899 bool isChrome = (aCallerType == CallerType::System);
2900 bool privileged =
2901 isChrome ||
2902 Preferences::GetBool("media.navigator.permission.disabled", false);
2903 bool isSecure = aWindow->IsSecureContext();
2904 bool isHandlingUserInput = UserActivation::IsHandlingUserInput();
2905 nsCString host;
2906 nsresult rv = docURI->GetHost(host);
Value stored to 'rv' during its initialization is never read
2907
2908 nsCOMPtr<nsIPrincipal> principal =
2909 nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
2910 if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2910)
) {
2911 return StreamPromise::CreateAndReject(
2912 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError),
2913 __func__);
2914 }
2915
2916 Document* doc = aWindow->GetExtantDoc();
2917 if (NS_WARN_IF(!doc)NS_warn_if_impl(!doc, "!doc", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2917)
) {
2918 return StreamPromise::CreateAndReject(
2919 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError),
2920 __func__);
2921 }
2922
2923 // Disallow access to null principal pages and http pages (unless pref)
2924 if (principal->GetIsNullPrincipal() ||
2925 !(isSecure || StaticPrefs::media_getusermedia_insecure_enabled())) {
2926 return StreamPromise::CreateAndReject(
2927 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError),
2928 __func__);
2929 }
2930
2931 // This principal needs to be sent to different threads and so via IPC.
2932 // For this reason it's better to convert it to PrincipalInfo right now.
2933 ipc::PrincipalInfo principalInfo;
2934 rv = PrincipalToPrincipalInfo(principal, &principalInfo);
2935 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 2935)
) {
2936 return StreamPromise::CreateAndReject(
2937 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError),
2938 __func__);
2939 }
2940
2941 const bool resistFingerprinting =
2942 !isChrome && doc->ShouldResistFingerprinting(RFPTarget::MediaDevices);
2943 if (resistFingerprinting) {
2944 ReduceConstraint(c.mVideo);
2945 ReduceConstraint(c.mAudio);
2946 }
2947
2948 if (!Preferences::GetBool("media.navigator.video.enabled", true)) {
2949 c.mVideo.SetAsBoolean() = false;
2950 }
2951
2952 MediaSourceEnum videoType = MediaSourceEnum::Other; // none
2953 MediaSourceEnum audioType = MediaSourceEnum::Other; // none
2954
2955 if (c.mVideo.IsMediaTrackConstraints()) {
2956 auto& vc = c.mVideo.GetAsMediaTrackConstraints();
2957 if (!vc.mMediaSource.WasPassed()) {
2958 vc.mMediaSource.Construct().AssignASCII(
2959 dom::GetEnumString(MediaSourceEnum::Camera));
2960 }
2961 videoType = dom::StringToEnum<MediaSourceEnum>(vc.mMediaSource.Value())
2962 .valueOr(MediaSourceEnum::Other);
2963 glean::webrtc::get_user_media_type.AccumulateSingleSample(
2964 (uint32_t)videoType);
2965 switch (videoType) {
2966 case MediaSourceEnum::Camera:
2967 break;
2968
2969 case MediaSourceEnum::Browser:
2970 // If no window id is passed in then default to the caller's window.
2971 // Functional defaults are helpful in tests, but also a natural outcome
2972 // of the constraints API's limited semantics for requiring input.
2973 if (!vc.mBrowserWindow.WasPassed()) {
2974 nsPIDOMWindowOuter* outer = aWindow->GetOuterWindow();
2975 vc.mBrowserWindow.Construct(outer->WindowID());
2976 }
2977 [[fallthrough]];
2978 case MediaSourceEnum::Screen:
2979 case MediaSourceEnum::Window:
2980 // Deny screensharing request if support is disabled, or
2981 // the requesting document is not from a host on the whitelist.
2982 if (!Preferences::GetBool(
2983 ((videoType == MediaSourceEnum::Browser)
2984 ? "media.getusermedia.browser.enabled"
2985 : "media.getusermedia.screensharing.enabled"),
2986 false) ||
2987 (!privileged && !aWindow->IsSecureContext())) {
2988 return StreamPromise::CreateAndReject(
2989 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError),
2990 __func__);
2991 }
2992 break;
2993
2994 case MediaSourceEnum::Microphone:
2995 case MediaSourceEnum::Other:
2996 default: {
2997 return StreamPromise::CreateAndReject(
2998 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::OverconstrainedError,
2999 "", u"mediaSource"_ns),
3000 __func__);
3001 }
3002 }
3003
3004 if (!privileged) {
3005 // Only allow privileged content to explicitly pick full-screen,
3006 // application or tabsharing, since these modes are still available for
3007 // testing. All others get "Window" (*) sharing.
3008 //
3009 // *) We overload "Window" with the new default getDisplayMedia spec-
3010 // mandated behavior of not influencing user-choice, which we currently
3011 // implement as a list containing BOTH windows AND screen(s).
3012 //
3013 // Notes on why we chose "Window" as the one to overload. Two reasons:
3014 //
3015 // 1. It's the closest logically & behaviorally (multi-choice, no default)
3016 // 2. Screen is still useful in tests (implicit default is entire screen)
3017 //
3018 // For UX reasons we don't want "Entire Screen" to be the first/default
3019 // choice (in our code first=default). It's a "scary" source that comes
3020 // with complicated warnings on-top that would be confusing as the first
3021 // thing people see, and also deserves to be listed as last resort for
3022 // privacy reasons.
3023
3024 if (videoType == MediaSourceEnum::Screen ||
3025 videoType == MediaSourceEnum::Browser) {
3026 videoType = MediaSourceEnum::Window;
3027 vc.mMediaSource.Value().AssignASCII(dom::GetEnumString(videoType));
3028 }
3029 // only allow privileged content to set the window id
3030 if (vc.mBrowserWindow.WasPassed()) {
3031 vc.mBrowserWindow.Value() = -1;
3032 }
3033 if (vc.mAdvanced.WasPassed()) {
3034 for (MediaTrackConstraintSet& cs : vc.mAdvanced.Value()) {
3035 if (cs.mBrowserWindow.WasPassed()) {
3036 cs.mBrowserWindow.Value() = -1;
3037 }
3038 }
3039 }
3040 }
3041 } else if (IsOn(c.mVideo)) {
3042 videoType = MediaSourceEnum::Camera;
3043 glean::webrtc::get_user_media_type.AccumulateSingleSample(
3044 (uint32_t)videoType);
3045 }
3046
3047 if (c.mAudio.IsMediaTrackConstraints()) {
3048 auto& ac = c.mAudio.GetAsMediaTrackConstraints();
3049 if (!ac.mMediaSource.WasPassed()) {
3050 ac.mMediaSource.Construct(NS_ConvertASCIItoUTF16(
3051 dom::GetEnumString(MediaSourceEnum::Microphone)));
3052 }
3053 audioType = dom::StringToEnum<MediaSourceEnum>(ac.mMediaSource.Value())
3054 .valueOr(MediaSourceEnum::Other);
3055 glean::webrtc::get_user_media_type.AccumulateSingleSample(
3056 (uint32_t)audioType);
3057
3058 switch (audioType) {
3059 case MediaSourceEnum::Microphone:
3060 break;
3061
3062 case MediaSourceEnum::AudioCapture:
3063 // Only enable AudioCapture if the pref is enabled. If it's not, we can
3064 // deny right away.
3065 if (!Preferences::GetBool("media.getusermedia.audio.capture.enabled")) {
3066 return StreamPromise::CreateAndReject(
3067 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError),
3068 __func__);
3069 }
3070 break;
3071
3072 case MediaSourceEnum::Other:
3073 default: {
3074 return StreamPromise::CreateAndReject(
3075 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::OverconstrainedError,
3076 "", u"mediaSource"_ns),
3077 __func__);
3078 }
3079 }
3080 } else if (IsOn(c.mAudio)) {
3081 audioType = MediaSourceEnum::Microphone;
3082 glean::webrtc::get_user_media_type.AccumulateSingleSample(
3083 (uint32_t)audioType);
3084 }
3085
3086 // Create a window listener if it doesn't already exist.
3087 RefPtr<GetUserMediaWindowListener> windowListener =
3088 GetOrMakeWindowListener(aWindow);
3089 MOZ_ASSERT(windowListener)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(windowListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(windowListener))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("windowListener"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3089); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "windowListener" ")"); do { MOZ_CrashSequence
(__null, 3089); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3090 // Create an inactive DeviceListener to act as a placeholder, so the
3091 // window listener doesn't clean itself up until we're done.
3092 auto placeholderListener = MakeRefPtr<DeviceListener>();
3093 windowListener->Register(placeholderListener);
3094
3095 { // Check Permissions Policy. Reject if a requested feature is disabled.
3096 bool disabled = !IsOn(c.mAudio) && !IsOn(c.mVideo);
3097 if (IsOn(c.mAudio)) {
3098 if (audioType == MediaSourceEnum::Microphone) {
3099 if (Preferences::GetBool("media.getusermedia.microphone.deny", false) ||
3100 !FeaturePolicyUtils::IsFeatureAllowed(doc, u"microphone"_ns)) {
3101 disabled = true;
3102 }
3103 } else if (!FeaturePolicyUtils::IsFeatureAllowed(doc,
3104 u"display-capture"_ns)) {
3105 disabled = true;
3106 }
3107 }
3108 if (IsOn(c.mVideo)) {
3109 if (videoType == MediaSourceEnum::Camera) {
3110 if (Preferences::GetBool("media.getusermedia.camera.deny", false) ||
3111 !FeaturePolicyUtils::IsFeatureAllowed(doc, u"camera"_ns)) {
3112 disabled = true;
3113 }
3114 } else if (!FeaturePolicyUtils::IsFeatureAllowed(doc,
3115 u"display-capture"_ns)) {
3116 disabled = true;
3117 }
3118 }
3119
3120 if (disabled) {
3121 placeholderListener->Stop();
3122 return StreamPromise::CreateAndReject(
3123 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError),
3124 __func__);
3125 }
3126 }
3127
3128 // Get list of all devices, with origin-specific device ids.
3129
3130 MediaEnginePrefs prefs = mPrefs;
3131
3132 nsString callID;
3133 rv = GenerateUUID(callID);
3134 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3134); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 3134); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3135
3136 bool hasVideo = videoType != MediaSourceEnum::Other;
3137 bool hasAudio = audioType != MediaSourceEnum::Other;
3138
3139 // Handle fake requests from content. For gUM we don't consider resist
3140 // fingerprinting as users should be prompted anyway.
3141 bool forceFakes = c.mFake.WasPassed() && c.mFake.Value();
3142 // fake:true is effective only for microphone and camera devices, so
3143 // permission must be requested for screen capture even if fake:true is set.
3144 bool hasOnlyForcedFakes =
3145 forceFakes && (!hasVideo || videoType == MediaSourceEnum::Camera) &&
3146 (!hasAudio || audioType == MediaSourceEnum::Microphone);
3147 bool askPermission =
3148 (!privileged ||
3149 Preferences::GetBool("media.navigator.permission.force")) &&
3150 (!hasOnlyForcedFakes ||
3151 Preferences::GetBool("media.navigator.permission.fake"));
3152
3153 LOG("%s: Preparing to enumerate devices. windowId=%" PRIu64"l" "u"
3154 ", videoType=%" PRIu8"u" ", audioType=%" PRIu8"u"
3155 ", forceFakes=%s, askPermission=%s",
3156 __func__, windowID, static_cast<uint8_t>(videoType),
3157 static_cast<uint8_t>(audioType), forceFakes ? "true" : "false",
3158 askPermission ? "true" : "false");
3159
3160 EnumerationFlags flags = EnumerationFlag::AllowPermissionRequest;
3161 if (forceFakes) {
3162 flags += EnumerationFlag::ForceFakes;
3163 }
3164 RefPtr<MediaManager> self = this;
3165 return EnumerateDevicesImpl(
3166 aWindow, CreateEnumerationParams(videoType, audioType, flags))
3167 ->Then(
3168 GetCurrentSerialEventTarget(), __func__,
3169 [self, windowID, c, windowListener,
3170 aCallerType](RefPtr<LocalMediaDeviceSetRefCnt> aDevices) {
3171 LOG("GetUserMedia: post enumeration promise success callback "
3172 "starting");
3173 // Ensure that our windowID is still good.
3174 RefPtr<nsPIDOMWindowInner> window =
3175 nsGlobalWindowInner::GetInnerWindowWithId(windowID);
3176 if (!window || !self->IsWindowListenerStillActive(windowListener)) {
3177 LOG("GetUserMedia: bad window (%" PRIu64"l" "u"
3178 ") in post enumeration success callback!",
3179 windowID);
3180 return LocalDeviceSetPromise::CreateAndReject(
3181 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError),
3182 __func__);
3183 }
3184 // Apply any constraints. This modifies the passed-in list.
3185 return self->SelectSettings(c, aCallerType, std::move(aDevices));
3186 },
3187 [](RefPtr<MediaMgrError>&& aError) {
3188 LOG("GetUserMedia: post enumeration EnumerateDevicesImpl "
3189 "failure callback called!");
3190 return LocalDeviceSetPromise::CreateAndReject(std::move(aError),
3191 __func__);
3192 })
3193 ->Then(
3194 GetCurrentSerialEventTarget(), __func__,
3195 [self, windowID, c, windowListener, placeholderListener, hasAudio,
3196 hasVideo, askPermission, prefs, isSecure, isHandlingUserInput,
3197 callID, principalInfo, aCallerType, resistFingerprinting,
3198 audioType](RefPtr<LocalMediaDeviceSetRefCnt> aDevices) mutable {
3199 LOG("GetUserMedia: starting post enumeration promise2 success "
3200 "callback!");
3201
3202 // Ensure that the window is still good.
3203 RefPtr<nsPIDOMWindowInner> window =
3204 nsGlobalWindowInner::GetInnerWindowWithId(windowID);
3205 if (!window || !self->IsWindowListenerStillActive(windowListener)) {
3206 LOG("GetUserMedia: bad window (%" PRIu64"l" "u"
3207 ") in post enumeration success callback 2!",
3208 windowID);
3209 placeholderListener->Stop();
3210 return StreamPromise::CreateAndReject(
3211 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError),
3212 __func__);
3213 }
3214 if (!aDevices->Length()) {
3215 LOG("GetUserMedia: no devices found in post enumeration promise2 "
3216 "success callback! Calling error handler!");
3217 placeholderListener->Stop();
3218 // When privacy.resistFingerprinting = true, no
3219 // available device implies content script is requesting
3220 // a fake device, so report NotAllowedError.
3221 auto error = resistFingerprinting
3222 ? MediaMgrError::Name::NotAllowedError
3223 : MediaMgrError::Name::NotFoundError;
3224 return StreamPromise::CreateAndReject(
3225 MakeRefPtr<MediaMgrError>(error), __func__);
3226 }
3227
3228 // Time to start devices. Create the necessary device listeners and
3229 // remove the placeholder.
3230 RefPtr<DeviceListener> audioListener;
3231 RefPtr<DeviceListener> videoListener;
3232 if (hasAudio) {
3233 audioListener = MakeRefPtr<DeviceListener>();
3234 windowListener->Register(audioListener);
3235 }
3236 if (hasVideo) {
3237 videoListener = MakeRefPtr<DeviceListener>();
3238 windowListener->Register(videoListener);
3239 }
3240 placeholderListener->Stop();
3241
3242 bool focusSource = mozilla::Preferences::GetBool(
3243 "media.getusermedia.window.focus_source.enabled", true);
3244
3245 // Incremental hack to compile. To be replaced by deeper
3246 // refactoring. MediaManager allows
3247 // "neither-resolve-nor-reject" semantics, so we cannot
3248 // use MozPromiseHolder here.
3249 MozPromiseHolder<StreamPromise> holder;
3250 RefPtr<StreamPromise> p = holder.Ensure(__func__);
3251
3252 // Pass callbacks and listeners along to GetUserMediaStreamTask.
3253 auto task = MakeRefPtr<GetUserMediaStreamTask>(
3254 c, std::move(holder), windowID, std::move(windowListener),
3255 std::move(audioListener), std::move(videoListener), prefs,
3256 principalInfo, aCallerType, focusSource);
3257
3258 // It is time to ask for user permission, prime voice processing
3259 // now. Use a local lambda to enable a guard pattern.
3260 [&] {
3261 if (audioType != MediaSourceEnum::Microphone) {
3262 return;
3263 }
3264
3265 if (!StaticPrefs::
3266 media_getusermedia_microphone_voice_stream_priming_enabled() ||
3267 !StaticPrefs::
3268 media_getusermedia_microphone_prefer_voice_stream_with_processing_enabled()) {
3269 return;
3270 }
3271
3272 if (const auto fc = FlattenedConstraints(
3273 NormalizedConstraints(GetInvariant(c.mAudio)));
3274 !fc.mEchoCancellation.Get(prefs.mAecOn) &&
3275 !fc.mAutoGainControl.Get(prefs.mAgcOn && prefs.mAecOn) &&
3276 !fc.mNoiseSuppression.Get(prefs.mNoiseOn && prefs.mAecOn)) {
3277 return;
3278 }
3279
3280 if (GetPersistentPermissions(windowID)
3281 .map([](auto&& aState) {
3282 return aState.mMicrophonePermission ==
3283 PersistentPermissionState::Deny;
3284 })
3285 .unwrapOr(true)) {
3286 return;
3287 }
3288
3289 task->PrimeVoiceProcessing();
3290 }();
3291
3292 size_t taskCount =
3293 self->AddTaskAndGetCount(windowID, callID, std::move(task));
3294
3295 if (!askPermission) {
3296 self->NotifyAllowed(callID, *aDevices);
3297 } else {
3298 auto req = MakeRefPtr<GetUserMediaRequest>(
3299 window, callID, std::move(aDevices), c, isSecure,
3300 isHandlingUserInput);
3301 if (!Preferences::GetBool("media.navigator.permission.force") &&
3302 taskCount > 1) {
3303 // there is at least 1 pending gUM request
3304 // For the scarySources test case, always send the
3305 // request
3306 self->mPendingGUMRequest.AppendElement(req.forget());
3307 } else {
3308 nsCOMPtr<nsIObserverService> obs =
3309 services::GetObserverService();
3310 obs->NotifyObservers(req, "getUserMedia:request", nullptr);
3311 }
3312 }
3313#ifdef MOZ_WEBRTC1
3314 self->mLogHandle = EnsureWebrtcLogging();
3315#endif
3316 return p;
3317 },
3318 [placeholderListener](RefPtr<MediaMgrError>&& aError) {
3319 LOG("GetUserMedia: post enumeration SelectSettings failure "
3320 "callback called!");
3321 placeholderListener->Stop();
3322 return StreamPromise::CreateAndReject(std::move(aError), __func__);
3323 });
3324};
3325
3326RefPtr<LocalDeviceSetPromise> MediaManager::AnonymizeDevices(
3327 nsPIDOMWindowInner* aWindow, RefPtr<const MediaDeviceSetRefCnt> aDevices) {
3328 // Get an origin-key (for either regular or private browsing).
3329 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/MediaManager.cpp", 3329); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 3329); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3330 uint64_t windowId = aWindow->WindowID();
3331 nsCOMPtr<nsIPrincipal> principal =
3332 nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
3333 MOZ_ASSERT(principal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(principal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(principal))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("principal", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3333); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal" ")"
); do { MOZ_CrashSequence(__null, 3333); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3334 ipc::PrincipalInfo principalInfo;
3335 nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo);
3336 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3336)
) {
3337 return LocalDeviceSetPromise::CreateAndReject(
3338 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError),
3339 __func__);
3340 }
3341 bool resistFingerprinting =
3342 aWindow->AsGlobal()->ShouldResistFingerprinting(RFPTarget::MediaDevices);
3343 bool persist =
3344 IsActivelyCapturingOrHasAPermission(windowId) && !resistFingerprinting;
3345 return media::GetPrincipalKey(principalInfo, persist)
3346 ->Then(
3347 GetMainThreadSerialEventTarget(), __func__,
3348 [rawDevices = std::move(aDevices), windowId,
3349 resistFingerprinting](const nsCString& aOriginKey) {
3350 MOZ_ASSERT(!aOriginKey.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aOriginKey.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aOriginKey.IsEmpty()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!aOriginKey.IsEmpty()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3350); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOriginKey.IsEmpty()" ")"); do { MOZ_CrashSequence
(__null, 3350); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3351 RefPtr anonymized = new LocalMediaDeviceSetRefCnt();
3352 for (const RefPtr<MediaDevice>& device : *rawDevices) {
3353 nsString name = device->mRawName;
3354 if (name.Find(u"AirPods"_ns) != -1) {
3355 name = u"AirPods"_ns;
3356 }
3357
3358 nsString id = device->mRawID;
3359 if (resistFingerprinting) {
3360 nsRFPService::GetMediaDeviceName(name, device->mKind);
3361 id = name;
3362 id.AppendInt(windowId);
3363 }
3364 // An empty id represents a virtual default device, for which
3365 // the exposed deviceId is the empty string.
3366 if (!id.IsEmpty()) {
3367 nsContentUtils::AnonymizeId(id, aOriginKey);
3368 }
3369
3370 nsString groupId = device->mRawGroupID;
3371 if (resistFingerprinting) {
3372 nsRFPService::GetMediaDeviceGroup(groupId, device->mKind);
3373 }
3374 // Use window id to salt group id in order to make it session
3375 // based as required by the spec. This does not provide unique
3376 // group ids through out a browser restart. However, this is not
3377 // against the spec. Furthermore, since device ids are the same
3378 // after a browser restart the fingerprint is not bigger.
3379 groupId.AppendInt(windowId);
3380 nsContentUtils::AnonymizeId(groupId, aOriginKey);
3381 anonymized->EmplaceBack(
3382 new LocalMediaDevice(device, id, groupId, name));
3383 }
3384 return LocalDeviceSetPromise::CreateAndResolve(anonymized,
3385 __func__);
3386 },
3387 [](nsresult rs) {
3388 NS_WARNING("AnonymizeDevices failed to get Principal Key")NS_DebugBreak(NS_DEBUG_WARNING, "AnonymizeDevices failed to get Principal Key"
, nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp", 3388
)
;
3389 return LocalDeviceSetPromise::CreateAndReject(
3390 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError),
3391 __func__);
3392 });
3393}
3394
3395RefPtr<LocalDeviceSetPromise> MediaManager::EnumerateDevicesImpl(
3396 nsPIDOMWindowInner* aWindow, EnumerationParams aParams) {
3397 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/MediaManager.cpp", 3397); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 3397); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3398
3399 uint64_t windowId = aWindow->WindowID();
3400 LOG("%s: windowId=%" PRIu64"l" "u" ", aVideoInputType=%" PRIu8"u"
3401 ", aAudioInputType=%" PRIu8"u",
3402 __func__, windowId, static_cast<uint8_t>(aParams.VideoInputType()),
3403 static_cast<uint8_t>(aParams.AudioInputType()));
3404
3405 // To get a device list anonymized for a particular origin, we must:
3406 // 1. Get the raw devices list
3407 // 2. Anonymize the raw list with an origin-key.
3408
3409 // Add the window id here to check for that and abort silently if no longer
3410 // exists.
3411 RefPtr<GetUserMediaWindowListener> windowListener =
3412 GetOrMakeWindowListener(aWindow);
3413 MOZ_ASSERT(windowListener)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(windowListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(windowListener))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("windowListener"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3413); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "windowListener" ")"); do { MOZ_CrashSequence
(__null, 3413); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3414 // Create an inactive DeviceListener to act as a placeholder, so the
3415 // window listener doesn't clean itself up until we're done.
3416 auto placeholderListener = MakeRefPtr<DeviceListener>();
3417 windowListener->Register(placeholderListener);
3418
3419 return MaybeRequestPermissionAndEnumerateRawDevices(std::move(aParams))
3420 ->Then(
3421 GetMainThreadSerialEventTarget(), __func__,
3422 [self = RefPtr(this), this, window = nsCOMPtr(aWindow),
3423 placeholderListener](RefPtr<MediaDeviceSetRefCnt> aDevices) mutable {
3424 // Only run if window is still on our active list.
3425 MediaManager* mgr = MediaManager::GetIfExists();
3426 if (!mgr || placeholderListener->Stopped()) {
3427 // The listener has already been removed if the window is no
3428 // longer active.
3429 return LocalDeviceSetPromise::CreateAndReject(
3430 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError),
3431 __func__);
3432 }
3433 MOZ_ASSERT(mgr->IsWindowStillActive(window->WindowID()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mgr->IsWindowStillActive(window->WindowID()))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mgr->IsWindowStillActive(window->WindowID())))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mgr->IsWindowStillActive(window->WindowID())"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3433); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mgr->IsWindowStillActive(window->WindowID())"
")"); do { MOZ_CrashSequence(__null, 3433); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3434 placeholderListener->Stop();
3435 return AnonymizeDevices(window, aDevices);
3436 },
3437 [placeholderListener](RefPtr<MediaMgrError>&& aError) {
3438 // EnumerateDevicesImpl may fail if a new doc has been set, in which
3439 // case the OnNavigation() method should have removed all previous
3440 // active listeners, or if a platform device access request was not
3441 // granted.
3442 placeholderListener->Stop();
3443 return LocalDeviceSetPromise::CreateAndReject(std::move(aError),
3444 __func__);
3445 });
3446}
3447
3448RefPtr<LocalDevicePromise> MediaManager::SelectAudioOutput(
3449 nsPIDOMWindowInner* aWindow, const dom::AudioOutputOptions& aOptions,
3450 CallerType aCallerType) {
3451 bool isHandlingUserInput = UserActivation::IsHandlingUserInput();
3452 nsCOMPtr<nsIPrincipal> principal =
3453 nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
3454 if (!FeaturePolicyUtils::IsFeatureAllowed(aWindow->GetExtantDoc(),
3455 u"speaker-selection"_ns)) {
3456 return LocalDevicePromise::CreateAndReject(
3457 MakeRefPtr<MediaMgrError>(
3458 MediaMgrError::Name::NotAllowedError,
3459 "Document's Permissions Policy does not allow selectAudioOutput()"),
3460 __func__);
3461 }
3462 if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3462)
) {
3463 return LocalDevicePromise::CreateAndReject(
3464 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError),
3465 __func__);
3466 }
3467 // Disallow access to null principal.
3468 if (principal->GetIsNullPrincipal()) {
3469 return LocalDevicePromise::CreateAndReject(
3470 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError),
3471 __func__);
3472 }
3473 ipc::PrincipalInfo principalInfo;
3474 nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo);
3475 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3475)
) {
3476 return LocalDevicePromise::CreateAndReject(
3477 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError),
3478 __func__);
3479 }
3480 uint64_t windowID = aWindow->WindowID();
3481 const bool resistFingerprinting =
3482 aWindow->AsGlobal()->ShouldResistFingerprinting(aCallerType,
3483 RFPTarget::MediaDevices);
3484 return EnumerateDevicesImpl(
3485 aWindow, CreateEnumerationParams(
3486 MediaSourceEnum::Other, MediaSourceEnum::Other,
3487 {EnumerationFlag::EnumerateAudioOutputs,
3488 EnumerationFlag::AllowPermissionRequest}))
3489 ->Then(
3490 GetCurrentSerialEventTarget(), __func__,
3491 [self = RefPtr<MediaManager>(this), windowID, aOptions, aCallerType,
3492 resistFingerprinting, isHandlingUserInput,
3493 principalInfo](RefPtr<LocalMediaDeviceSetRefCnt> aDevices) mutable {
3494 // Ensure that the window is still good.
3495 RefPtr<nsPIDOMWindowInner> window =
3496 nsGlobalWindowInner::GetInnerWindowWithId(windowID);
3497 if (!window) {
3498 LOG("SelectAudioOutput: bad window (%" PRIu64"l" "u"
3499 ") in post enumeration success callback!",
3500 windowID);
3501 return LocalDevicePromise::CreateAndReject(
3502 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError),
3503 __func__);
3504 }
3505 if (aDevices->IsEmpty()) {
3506 LOG("SelectAudioOutput: no devices found");
3507 auto error = resistFingerprinting
3508 ? MediaMgrError::Name::NotAllowedError
3509 : MediaMgrError::Name::NotFoundError;
3510 return LocalDevicePromise::CreateAndReject(
3511 MakeRefPtr<MediaMgrError>(error), __func__);
3512 }
3513 MozPromiseHolder<LocalDevicePromise> holder;
3514 RefPtr<LocalDevicePromise> p = holder.Ensure(__func__);
3515 auto task = MakeRefPtr<SelectAudioOutputTask>(
3516 std::move(holder), windowID, aCallerType, principalInfo);
3517 nsString callID;
3518 nsresult rv = GenerateUUID(callID);
3519 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3519); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 3519); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3520 size_t taskCount =
3521 self->AddTaskAndGetCount(windowID, callID, std::move(task));
3522 bool askPermission =
3523 !Preferences::GetBool("media.navigator.permission.disabled") ||
3524 Preferences::GetBool("media.navigator.permission.force");
3525 if (!askPermission) {
3526 self->NotifyAllowed(callID, *aDevices);
3527 } else {
3528 MOZ_ASSERT(window->IsSecureContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(window->IsSecureContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(window->IsSecureContext()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"window->IsSecureContext()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "window->IsSecureContext()"
")"); do { MOZ_CrashSequence(__null, 3528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3529 auto req = MakeRefPtr<GetUserMediaRequest>(
3530 window, callID, std::move(aDevices), aOptions, true,
3531 isHandlingUserInput);
3532 if (taskCount > 1) {
3533 // there is at least 1 pending gUM request
3534 self->mPendingGUMRequest.AppendElement(req.forget());
3535 } else {
3536 nsCOMPtr<nsIObserverService> obs =
3537 services::GetObserverService();
3538 obs->NotifyObservers(req, "getUserMedia:request", nullptr);
3539 }
3540 }
3541 return p;
3542 },
3543 [](RefPtr<MediaMgrError> aError) {
3544 LOG("SelectAudioOutput: EnumerateDevicesImpl "
3545 "failure callback called!");
3546 return LocalDevicePromise::CreateAndReject(std::move(aError),
3547 __func__);
3548 });
3549}
3550
3551MediaEngine* MediaManager::GetBackend() {
3552 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3552); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 3552); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3553 // Plugin backends as appropriate. The default engine also currently
3554 // includes picture support for Android.
3555 // This IS called off main-thread.
3556 if (!mBackend) {
3557#if defined(MOZ_WEBRTC1)
3558 mBackend = new MediaEngineWebRTC();
3559#else
3560 mBackend = new MediaEngineFake();
3561#endif
3562 mDeviceListChangeListener = mBackend->DeviceListChangeEvent().Connect(
3563 AbstractThread::MainThread(), this, &MediaManager::DeviceListChanged);
3564 }
3565 return mBackend;
3566}
3567
3568void MediaManager::OnNavigation(uint64_t aWindowID) {
3569 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/MediaManager.cpp", 3569); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 3569); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3570 LOG("OnNavigation for %" PRIu64"l" "u", aWindowID);
3571
3572 // Stop the streams for this window. The runnables check this value before
3573 // making a call to content.
3574
3575 nsTArray<nsString>* callIDs;
3576 if (mCallIds.Get(aWindowID, &callIDs)) {
3577 for (auto& callID : *callIDs) {
3578 mActiveCallbacks.Remove(callID);
3579 for (auto& request : mPendingGUMRequest.Clone()) {
3580 nsString id;
3581 request->GetCallID(id);
3582 if (id == callID) {
3583 mPendingGUMRequest.RemoveElement(request);
3584 }
3585 }
3586 }
3587 mCallIds.Remove(aWindowID);
3588 }
3589
3590 if (RefPtr<GetUserMediaWindowListener> listener =
3591 GetWindowListener(aWindowID)) {
3592 listener->RemoveAll();
3593 }
3594 MOZ_ASSERT(!GetWindowListener(aWindowID))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!GetWindowListener(aWindowID))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!GetWindowListener(aWindowID
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!GetWindowListener(aWindowID)", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3594); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowListener(aWindowID)"
")"); do { MOZ_CrashSequence(__null, 3594); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3595}
3596
3597void MediaManager::OnCameraMute(bool aMute) {
3598 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/MediaManager.cpp", 3598); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 3598); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3599 LOG("OnCameraMute for all windows");
3600 mCamerasMuted = aMute;
3601 // This is safe since we're on main-thread, and the windowlist can only
3602 // be added to from the main-thread
3603 for (const auto& window :
3604 ToTArray<AutoTArray<RefPtr<GetUserMediaWindowListener>, 2>>(
3605 mActiveWindows.Values())) {
3606 window->MuteOrUnmuteCameras(aMute);
3607 }
3608}
3609
3610void MediaManager::OnMicrophoneMute(bool aMute) {
3611 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/MediaManager.cpp", 3611); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 3611); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3612 LOG("OnMicrophoneMute for all windows");
3613 mMicrophonesMuted = aMute;
3614 // This is safe since we're on main-thread, and the windowlist can only
3615 // be added to from the main-thread
3616 for (const auto& window :
3617 ToTArray<AutoTArray<RefPtr<GetUserMediaWindowListener>, 2>>(
3618 mActiveWindows.Values())) {
3619 window->MuteOrUnmuteMicrophones(aMute);
3620 }
3621}
3622
3623RefPtr<GetUserMediaWindowListener> MediaManager::GetOrMakeWindowListener(
3624 nsPIDOMWindowInner* aWindow) {
3625 Document* doc = aWindow->GetExtantDoc();
3626 if (!doc) {
3627 // The window has been destroyed. Destroyed windows don't have listeners.
3628 return nullptr;
3629 }
3630 nsIPrincipal* principal = doc->NodePrincipal();
3631 uint64_t windowId = aWindow->WindowID();
3632 RefPtr<GetUserMediaWindowListener> windowListener =
3633 GetWindowListener(windowId);
3634 if (windowListener) {
3635 MOZ_ASSERT(PrincipalHandleMatches(windowListener->GetPrincipalHandle(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(PrincipalHandleMatches(windowListener->GetPrincipalHandle
(), principal))>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(PrincipalHandleMatches(windowListener
->GetPrincipalHandle(), principal)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3636); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)"
")"); do { MOZ_CrashSequence(__null, 3636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3636 principal))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(PrincipalHandleMatches(windowListener->GetPrincipalHandle
(), principal))>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(PrincipalHandleMatches(windowListener
->GetPrincipalHandle(), principal)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3636); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)"
")"); do { MOZ_CrashSequence(__null, 3636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3637 } else {
3638 windowListener = new GetUserMediaWindowListener(
3639 windowId, MakePrincipalHandle(principal));
3640 AddWindowID(windowId, windowListener);
3641 }
3642 return windowListener;
3643}
3644
3645void MediaManager::AddWindowID(uint64_t aWindowId,
3646 RefPtr<GetUserMediaWindowListener> aListener) {
3647 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/MediaManager.cpp", 3647); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 3647); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3648 // Store the WindowID in a hash table and mark as active. The entry is removed
3649 // when this window is closed or navigated away from.
3650 // This is safe since we're on main-thread, and the windowlist can only
3651 // be invalidated from the main-thread (see OnNavigation)
3652 if (IsWindowStillActive(aWindowId)) {
3653 MOZ_ASSERT(false, "Window already added")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Window already added"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 3653)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Window already added"
")"); do { MOZ_CrashSequence(__null, 3653); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3654 return;
3655 }
3656
3657 aListener->MuteOrUnmuteCameras(mCamerasMuted);
3658 aListener->MuteOrUnmuteMicrophones(mMicrophonesMuted);
3659 GetActiveWindows()->InsertOrUpdate(aWindowId, std::move(aListener));
3660
3661 RefPtr<WindowGlobalChild> wgc =
3662 WindowGlobalChild::GetByInnerWindowId(aWindowId);
3663 if (wgc) {
3664 wgc->BlockBFCacheFor(BFCacheStatus::ACTIVE_GET_USER_MEDIA);
3665 }
3666}
3667
3668void MediaManager::RemoveWindowID(uint64_t aWindowId) {
3669 RefPtr<WindowGlobalChild> wgc =
3670 WindowGlobalChild::GetByInnerWindowId(aWindowId);
3671 if (wgc) {
3672 wgc->UnblockBFCacheFor(BFCacheStatus::ACTIVE_GET_USER_MEDIA);
3673 }
3674
3675 mActiveWindows.Remove(aWindowId);
3676
3677 // get outer windowID
3678 auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowId);
3679 if (!window) {
3680 LOG("No inner window for %" PRIu64"l" "u", aWindowId);
3681 return;
3682 }
3683
3684 auto* outer = window->GetOuterWindow();
3685 if (!outer) {
3686 LOG("No outer window for inner %" PRIu64"l" "u", aWindowId);
3687 return;
3688 }
3689
3690 uint64_t outerID = outer->WindowID();
3691
3692 // Notify the UI that this window no longer has gUM active
3693 char windowBuffer[32];
3694 SprintfLiteral(windowBuffer, "%" PRIu64"l" "u", outerID);
3695 nsString data = NS_ConvertUTF8toUTF16(windowBuffer);
3696
3697 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
3698 obs->NotifyWhenScriptSafe(nullptr, "recording-window-ended", data.get());
3699 LOG("Sent recording-window-ended for window %" PRIu64"l" "u" " (outer %" PRIu64"l" "u" ")",
3700 aWindowId, outerID);
3701}
3702
3703bool MediaManager::IsWindowListenerStillActive(
3704 const RefPtr<GetUserMediaWindowListener>& aListener) {
3705 MOZ_DIAGNOSTIC_ASSERT(aListener)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aListener", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3705); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aListener"
")"); do { MOZ_CrashSequence(__null, 3705); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3706 return aListener && aListener == GetWindowListener(aListener->WindowID());
3707}
3708
3709void MediaManager::GetPref(nsIPrefBranch* aBranch, const char* aPref,
3710 const char* aData, int32_t* aVal) {
3711 int32_t temp;
3712 if (aData == nullptr || strcmp(aPref, aData) == 0) {
3713 if (NS_SUCCEEDED(aBranch->GetIntPref(aPref, &temp))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aBranch->GetIntPref
(aPref, &temp))), 1)))
) {
3714 *aVal = temp;
3715 }
3716 }
3717}
3718
3719void MediaManager::GetPrefBool(nsIPrefBranch* aBranch, const char* aPref,
3720 const char* aData, bool* aVal) {
3721 bool temp;
3722 if (aData == nullptr || strcmp(aPref, aData) == 0) {
3723 if (NS_SUCCEEDED(aBranch->GetBoolPref(aPref, &temp))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aBranch->GetBoolPref
(aPref, &temp))), 1)))
) {
3724 *aVal = temp;
3725 }
3726 }
3727}
3728
3729#ifdef MOZ_WEBRTC1
3730template <class Enum, class Int>
3731constexpr Enum ClampEnum(Int v) {
3732 return std::clamp(
3733 static_cast<Enum>(SaturatingCast<std::underlying_type_t<Enum>>(v)),
3734 ContiguousEnumValues<Enum>::min, ContiguousEnumValues<Enum>::max);
3735}
3736#endif
3737
3738void MediaManager::GetPrefs(nsIPrefBranch* aBranch, const char* aData) {
3739 GetPref(aBranch, "media.navigator.video.default_width", aData,
3740 &mPrefs.mWidth);
3741 GetPref(aBranch, "media.navigator.video.default_height", aData,
3742 &mPrefs.mHeight);
3743 GetPref(aBranch, "media.navigator.video.default_fps", aData, &mPrefs.mFPS);
3744 GetPref(aBranch, "media.navigator.audio.fake_frequency", aData,
3745 &mPrefs.mFreq);
3746#ifdef MOZ_WEBRTC1
3747 GetPrefBool(aBranch, "media.navigator.video.resize_mode.enabled", aData,
3748 &mPrefs.mResizeModeEnabled);
3749 int32_t resizeMode{};
3750 GetPref(aBranch, "media.navigator.video.default_resize_mode", aData,
3751 &resizeMode);
3752 mPrefs.mResizeMode = ClampEnum<VideoResizeModeEnum>(resizeMode);
3753 GetPrefBool(aBranch, "media.getusermedia.audio.processing.platform.enabled",
3754 aData, &mPrefs.mUsePlatformProcessing);
3755 GetPrefBool(aBranch, "media.getusermedia.audio.processing.aec.enabled", aData,
3756 &mPrefs.mAecOn);
3757 GetPrefBool(aBranch, "media.getusermedia.audio.processing.agc.enabled", aData,
3758 &mPrefs.mAgcOn);
3759 GetPrefBool(aBranch, "media.getusermedia.audio.processing.hpf.enabled", aData,
3760 &mPrefs.mHPFOn);
3761 GetPrefBool(aBranch, "media.getusermedia.audio.processing.noise.enabled",
3762 aData, &mPrefs.mNoiseOn);
3763 GetPrefBool(aBranch, "media.getusermedia.audio.processing.transient.enabled",
3764 aData, &mPrefs.mTransientOn);
3765 GetPrefBool(aBranch, "media.getusermedia.audio.processing.agc2.forced", aData,
3766 &mPrefs.mAgc2Forced);
3767 // Use 0 or 1 to force to false or true
3768 // EchoCanceller3Config::echo_removal_control.has_clock_drift.
3769 // -1 is the default, which means automatically set has_clock_drift as
3770 // deemed appropriate.
3771 GetPref(aBranch, "media.getusermedia.audio.processing.aec.expect_drift",
3772 aData, &mPrefs.mExpectDrift);
3773 GetPref(aBranch, "media.getusermedia.audio.processing.agc", aData,
3774 &mPrefs.mAgc);
3775 GetPref(aBranch, "media.getusermedia.audio.processing.noise", aData,
3776 &mPrefs.mNoise);
3777 GetPref(aBranch, "media.getusermedia.audio.max_channels", aData,
3778 &mPrefs.mChannels);
3779#endif
3780 LOG("%s: default prefs: %dx%d @%dfps, %dHz test tones, "
3781 "resize mode: %s, platform processing: %s, "
3782 "aec: %s, agc: %s, hpf: %s, noise: %s, drift: %s, agc level: %d, agc "
3783 "version: "
3784 "%s, noise level: %d, transient: %s, channels %d",
3785 __FUNCTION__, mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mFreq,
3786 mPrefs.mResizeModeEnabled ? dom::GetEnumString(mPrefs.mResizeMode).get()
3787 : "disabled",
3788 mPrefs.mUsePlatformProcessing ? "on" : "off",
3789 mPrefs.mAecOn ? "on" : "off", mPrefs.mAgcOn ? "on" : "off",
3790 mPrefs.mHPFOn ? "on" : "off", mPrefs.mNoiseOn ? "on" : "off",
3791 mPrefs.mExpectDrift < 0 ? "auto"
3792 : mPrefs.mExpectDrift ? "on"
3793 : "off",
3794 mPrefs.mAgc, mPrefs.mAgc2Forced ? "2" : "1", mPrefs.mNoise,
3795 mPrefs.mTransientOn ? "on" : "off", mPrefs.mChannels);
3796}
3797
3798void MediaManager::Shutdown() {
3799 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/MediaManager.cpp", 3799); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 3799); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3800 if (sHasMainThreadShutdown) {
3801 return;
3802 }
3803
3804 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
3805
3806 obs->RemoveObserver(this, "last-pb-context-exited");
3807 obs->RemoveObserver(this, "getUserMedia:privileged:allow");
3808 obs->RemoveObserver(this, "getUserMedia:response:allow");
3809 obs->RemoveObserver(this, "getUserMedia:response:deny");
3810 obs->RemoveObserver(this, "getUserMedia:response:noOSPermission");
3811 obs->RemoveObserver(this, "getUserMedia:revoke");
3812 obs->RemoveObserver(this, "getUserMedia:muteVideo");
3813 obs->RemoveObserver(this, "getUserMedia:unmuteVideo");
3814 obs->RemoveObserver(this, "getUserMedia:muteAudio");
3815 obs->RemoveObserver(this, "getUserMedia:unmuteAudio");
3816 obs->RemoveObserver(this, "application-background");
3817 obs->RemoveObserver(this, "application-foreground");
3818
3819 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1");
3820 if (prefs) {
3821 ForeachObservedPref([&](const nsLiteralCString& aPrefName) {
3822 prefs->RemoveObserver(aPrefName, this);
3823 });
3824 }
3825
3826 if (mDeviceChangeTimer) {
3827 mDeviceChangeTimer->Cancel();
3828 // Drop ref to MediaTimer early to avoid blocking SharedThreadPool shutdown
3829 mDeviceChangeTimer = nullptr;
3830 }
3831
3832 {
3833 // Close off any remaining active windows.
3834
3835 // Live capture at this point is rare but can happen. Stopping it will make
3836 // the window listeners attempt to remove themselves from the active windows
3837 // table. We cannot touch the table at point so we grab a copy of the window
3838 // listeners first.
3839 const auto listeners = ToArray(GetActiveWindows()->Values());
3840 for (const auto& listener : listeners) {
3841 listener->RemoveAll();
3842 }
3843 }
3844 MOZ_ASSERT(GetActiveWindows()->Count() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetActiveWindows()->Count() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetActiveWindows()->Count
() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetActiveWindows()->Count() == 0", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetActiveWindows()->Count() == 0"
")"); do { MOZ_CrashSequence(__null, 3844); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3845
3846 GetActiveWindows()->Clear();
3847 mActiveCallbacks.Clear();
3848 mCallIds.Clear();
3849 mPendingGUMRequest.Clear();
3850#ifdef MOZ_WEBRTC1
3851 mLogHandle = nullptr;
3852#endif
3853
3854 // From main thread's point of view, shutdown is now done.
3855 // All that remains is shutting down the media thread.
3856 sHasMainThreadShutdown = true;
3857
3858 // Release the backend (and call Shutdown()) from within mMediaThread.
3859 // Don't use MediaManager::Dispatch() because we're
3860 // sHasMainThreadShutdown == true here!
3861 MOZ_ALWAYS_SUCCEEDS(mMediaThread->Dispatch(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3862 NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3863 LOG("MediaManager Thread Shutdown");do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3864 MOZ_ASSERT(IsInMediaThread());do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3865 // Must shutdown backend on MediaManager thread, since that'sdo { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3866 // where we started it from!do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3867 if (mBackend) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3868 mBackend->Shutdown(); // idempotentdo { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3869 mDeviceListChangeListener.DisconnectIfExists();do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3870 }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3871 // last reference, will invoke Shutdown() againdo { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3872 mBackend = nullptr;do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3873 })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [
self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { MOZ_CrashSequence
(__null, 3864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); if (mBackend) { mBackend->Shutdown
(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend
= nullptr; })))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/root/firefox-clang/dom/media/MediaManager.cpp\", 3864); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { MOZ_CrashSequence(__null, 3864); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3874
3875 // note that this == sSingleton
3876 MOZ_ASSERT(this == sSingleton)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(this == sSingleton)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(this == sSingleton))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("this == sSingleton"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 3876); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "this == sSingleton" ")"); do { MOZ_CrashSequence
(__null, 3876); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3877
3878 // Explicitly shut down the TaskQueue so that it releases its
3879 // SharedThreadPool when all tasks have completed. SharedThreadPool blocks
3880 // XPCOM shutdown from proceeding beyond "xpcom-shutdown-threads" until all
3881 // SharedThreadPools are released, but the nsComponentManager keeps a
3882 // reference to the MediaManager for the nsIMediaManagerService until much
3883 // later in shutdown. This also provides additional assurance that no
3884 // further tasks will be queued.
3885 mMediaThread->BeginShutdown()->Then(
3886 GetMainThreadSerialEventTarget(), __func__, [] {
3887 LOG("MediaManager shutdown lambda running, releasing MediaManager "
3888 "singleton");
3889 // Remove async shutdown blocker
3890 media::MustGetShutdownBarrier()->RemoveBlocker(
3891 sSingleton->mShutdownBlocker);
3892
3893 sSingleton = nullptr;
3894 });
3895}
3896
3897void MediaManager::SendPendingGUMRequest() {
3898 if (mPendingGUMRequest.Length() > 0) {
3899 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
3900 obs->NotifyObservers(mPendingGUMRequest[0], "getUserMedia:request",
3901 nullptr);
3902 mPendingGUMRequest.RemoveElementAt(0);
3903 }
3904}
3905
3906bool IsGUMResponseNoAccess(const char* aTopic,
3907 MediaMgrError::Name& aErrorName) {
3908 if (!strcmp(aTopic, "getUserMedia:response:deny")) {
3909 aErrorName = MediaMgrError::Name::NotAllowedError;
3910 return true;
3911 }
3912
3913 if (!strcmp(aTopic, "getUserMedia:response:noOSPermission")) {
3914 aErrorName = MediaMgrError::Name::NotFoundError;
3915 return true;
3916 }
3917
3918 return false;
3919}
3920
3921static MediaSourceEnum ParseScreenColonWindowID(const char16_t* aData,
3922 uint64_t* aWindowIDOut) {
3923 MOZ_ASSERT(aWindowIDOut)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindowIDOut)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindowIDOut))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aWindowIDOut", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowIDOut"
")"); do { MOZ_CrashSequence(__null, 3923); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3924 // may be windowid or screen:windowid
3925 const nsDependentString data(aData);
3926 if (Substring(data, 0, strlen("screen:")).EqualsLiteral("screen:")) {
3927 nsresult rv;
3928 *aWindowIDOut = Substring(data, strlen("screen:")).ToInteger64(&rv);
3929 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3929); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 3929); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3930 return MediaSourceEnum::Screen;
3931 }
3932 nsresult rv;
3933 *aWindowIDOut = data.ToInteger64(&rv);
3934 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3934); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 3934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3935 return MediaSourceEnum::Camera;
3936}
3937
3938nsresult MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
3939 const char16_t* aData) {
3940 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/MediaManager.cpp", 3940); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 3940); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3941
3942 MediaMgrError::Name gumNoAccessError = MediaMgrError::Name::NotAllowedError;
3943
3944 if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID"nsPref:changed")) {
3945 nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(aSubject));
3946 if (branch) {
3947 GetPrefs(branch, NS_ConvertUTF16toUTF8(aData).get());
3948 DeviceListChanged();
3949 }
3950 } else if (!strcmp(aTopic, "last-pb-context-exited")) {
3951 // Clear memory of private-browsing-specific deviceIds. Fire and forget.
3952 media::SanitizeOriginKeys(0, true);
3953 return NS_OK;
3954 } else if (!strcmp(aTopic, "getUserMedia:got-device-permission")) {
3955 MOZ_ASSERT(aSubject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSubject)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSubject))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aSubject", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSubject" ")"
); do { MOZ_CrashSequence(__null, 3955); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3956 nsCOMPtr<nsIRunnable> task = do_QueryInterface(aSubject);
3957 MediaManager::Dispatch(NewTaskFrom([task] { task->Run(); }));
3958 return NS_OK;
3959 } else if (!strcmp(aTopic, "getUserMedia:privileged:allow") ||
3960 !strcmp(aTopic, "getUserMedia:response:allow")) {
3961 nsString key(aData);
3962 RefPtr<GetUserMediaTask> task = TakeGetUserMediaTask(key);
3963 if (!task) {
3964 return NS_OK;
3965 }
3966
3967 if (sHasMainThreadShutdown) {
3968 task->Denied(MediaMgrError::Name::AbortError, "In shutdown"_ns);
3969 return NS_OK;
3970 }
3971 if (NS_WARN_IF(!aSubject)NS_warn_if_impl(!aSubject, "!aSubject", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3971)
) {
3972 return NS_ERROR_FAILURE; // ignored
3973 }
3974 // Permission has been granted. aSubject contains the particular device
3975 // or devices selected and approved by the user, if any.
3976 nsCOMPtr<nsIArray> array(do_QueryInterface(aSubject));
3977 MOZ_ASSERT(array)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(array)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(array))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("array", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "array" ")")
; do { MOZ_CrashSequence(__null, 3977); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3978 uint32_t len = 0;
3979 array->GetLength(&len);
3980 RefPtr<LocalMediaDevice> audioInput;
3981 RefPtr<LocalMediaDevice> videoInput;
3982 RefPtr<LocalMediaDevice> audioOutput;
3983 for (uint32_t i = 0; i < len; i++) {
3984 nsCOMPtr<nsIMediaDevice> device;
3985 array->QueryElementAt(i, NS_GET_IID(nsIMediaDevice)(nsIMediaDevice::kIID),
3986 getter_AddRefs(device));
3987 MOZ_ASSERT(device)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(device)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(device))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("device", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 3987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "device" ")"
); do { MOZ_CrashSequence(__null, 3987); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // shouldn't be returning anything else...
3988 if (!device) {
3989 continue;
3990 }
3991
3992 // Casting here is safe because a LocalMediaDevice is created
3993 // only in Gecko side, JS can only query for an instance.
3994 auto* dev = static_cast<LocalMediaDevice*>(device.get());
3995 switch (dev->Kind()) {
3996 case MediaDeviceKind::Videoinput:
3997 if (!videoInput) {
3998 videoInput = dev;
3999 }
4000 break;
4001 case MediaDeviceKind::Audioinput:
4002 if (!audioInput) {
4003 audioInput = dev;
4004 }
4005 break;
4006 case MediaDeviceKind::Audiooutput:
4007 if (!audioOutput) {
4008 audioOutput = dev;
4009 }
4010 break;
4011 default:
4012 MOZ_CRASH("Unexpected device kind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected device kind"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 4012); AnnotateMozCrashReason
("MOZ_CRASH(" "Unexpected device kind" ")"); do { MOZ_CrashSequence
(__null, 4012); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
4013 }
4014 }
4015
4016 if (GetUserMediaStreamTask* streamTask = task->AsGetUserMediaStreamTask()) {
4017 bool needVideo = IsOn(streamTask->GetConstraints().mVideo);
4018 bool needAudio = IsOn(streamTask->GetConstraints().mAudio);
4019 MOZ_ASSERT(needVideo || needAudio)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(needVideo || needAudio)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(needVideo || needAudio))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("needVideo || needAudio"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 4019); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "needVideo || needAudio" ")"); do { MOZ_CrashSequence
(__null, 4019); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4020
4021 if ((needVideo && !videoInput) || (needAudio && !audioInput)) {
4022 task->Denied(MediaMgrError::Name::NotAllowedError);
4023 return NS_OK;
4024 }
4025 streamTask->Allowed(std::move(audioInput), std::move(videoInput));
4026 return NS_OK;
4027 }
4028 if (SelectAudioOutputTask* outputTask = task->AsSelectAudioOutputTask()) {
4029 if (!audioOutput) {
4030 task->Denied(MediaMgrError::Name::NotAllowedError);
4031 return NS_OK;
4032 }
4033 outputTask->Allowed(std::move(audioOutput));
4034 return NS_OK;
4035 }
4036
4037 NS_WARNING("Unknown task type in getUserMedia")NS_DebugBreak(NS_DEBUG_WARNING, "Unknown task type in getUserMedia"
, nullptr, "/root/firefox-clang/dom/media/MediaManager.cpp", 4037
)
;
4038 return NS_ERROR_FAILURE;
4039
4040 } else if (IsGUMResponseNoAccess(aTopic, gumNoAccessError)) {
4041 nsString key(aData);
4042 RefPtr<GetUserMediaTask> task = TakeGetUserMediaTask(key);
4043 if (task) {
4044 task->Denied(gumNoAccessError);
4045 SendPendingGUMRequest();
4046 }
4047 return NS_OK;
4048
4049 } else if (!strcmp(aTopic, "getUserMedia:revoke")) {
4050 uint64_t windowID;
4051 if (ParseScreenColonWindowID(aData, &windowID) == MediaSourceEnum::Screen) {
4052 LOG("Revoking ScreenCapture access for window %" PRIu64"l" "u", windowID);
4053 StopScreensharing(windowID);
4054 } else {
4055 LOG("Revoking MediaCapture access for window %" PRIu64"l" "u", windowID);
4056 OnNavigation(windowID);
4057 }
4058 return NS_OK;
4059 } else if (!strcmp(aTopic, "getUserMedia:muteVideo") ||
4060 !strcmp(aTopic, "getUserMedia:unmuteVideo")) {
4061 OnCameraMute(!strcmp(aTopic, "getUserMedia:muteVideo"));
4062 return NS_OK;
4063 } else if (!strcmp(aTopic, "getUserMedia:muteAudio") ||
4064 !strcmp(aTopic, "getUserMedia:unmuteAudio")) {
4065 OnMicrophoneMute(!strcmp(aTopic, "getUserMedia:muteAudio"));
4066 return NS_OK;
4067 } else if ((!strcmp(aTopic, "application-background") ||
4068 !strcmp(aTopic, "application-foreground")) &&
4069 StaticPrefs::media_getusermedia_camera_background_mute_enabled()) {
4070 // On mobile we turn off any cameras (but not mics) while in the background.
4071 // Keeping things simple for now by duplicating test-covered code above.
4072 //
4073 // NOTE: If a mobile device ever wants to implement "getUserMedia:muteVideo"
4074 // as well, it'd need to update this code to handle & test the combinations.
4075 OnCameraMute(!strcmp(aTopic, "application-background"));
4076 }
4077
4078 return NS_OK;
4079}
4080
4081NS_IMETHODIMPnsresult
4082MediaManager::CollectReports(nsIHandleReportCallback* aHandleReport,
4083 nsISupports* aData, bool aAnonymize) {
4084 size_t amount = 0;
4085 amount += mActiveWindows.ShallowSizeOfExcludingThis(MallocSizeOf);
4086 for (const GetUserMediaWindowListener* listener : mActiveWindows.Values()) {
4087 amount += listener->SizeOfIncludingThis(MallocSizeOf);
4088 }
4089 amount += mActiveCallbacks.ShallowSizeOfExcludingThis(MallocSizeOf);
4090 for (const GetUserMediaTask* task : mActiveCallbacks.Values()) {
4091 // Assume nsString buffers for keys are accounted in mCallIds.
4092 amount += task->SizeOfIncludingThis(MallocSizeOf);
4093 }
4094 amount += mCallIds.ShallowSizeOfExcludingThis(MallocSizeOf);
4095 for (const auto& array : mCallIds.Values()) {
4096 amount += array->ShallowSizeOfExcludingThis(MallocSizeOf);
4097 for (const nsString& callID : *array) {
4098 amount += callID.SizeOfExcludingThisEvenIfShared(MallocSizeOf);
4099 }
4100 }
4101 amount += mPendingGUMRequest.ShallowSizeOfExcludingThis(MallocSizeOf);
4102 // GetUserMediaRequest pointees of mPendingGUMRequest do not have support
4103 // for memory accounting. mPendingGUMRequest logic should probably be moved
4104 // to the front end (bug 1691625).
4105 MOZ_COLLECT_REPORT("explicit/media/media-manager-aggregates", KIND_HEAP,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/media/media-manager-aggregates"
), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by MediaManager variable length members."
), aData)
4106 UNITS_BYTES, amount,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/media/media-manager-aggregates"
), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by MediaManager variable length members."
), aData)
4107 "Memory used by MediaManager variable length members.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/media/media-manager-aggregates"
), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by MediaManager variable length members."
), aData)
;
4108 return NS_OK;
4109}
4110
4111nsresult MediaManager::GetActiveMediaCaptureWindows(nsIArray** aArray) {
4112 MOZ_ASSERT(aArray)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aArray)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aArray))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aArray", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4112); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aArray" ")"
); do { MOZ_CrashSequence(__null, 4112); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4113
4114 nsCOMPtr<nsIMutableArray> array = nsArray::Create();
4115
4116 for (const auto& entry : mActiveWindows) {
4117 const uint64_t& id = entry.GetKey();
4118 RefPtr<GetUserMediaWindowListener> winListener = entry.GetData();
4119 if (!winListener) {
4120 continue;
4121 }
4122
4123 auto* window = nsGlobalWindowInner::GetInnerWindowWithId(id);
4124 MOZ_ASSERT(window)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(window)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(window))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("window", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4124); AnnotateMozCrashReason("MOZ_ASSERT" "(" "window" ")"
); do { MOZ_CrashSequence(__null, 4124); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4125 // XXXkhuey ...
4126 if (!window) {
4127 continue;
4128 }
4129
4130 if (winListener->CapturingVideo() || winListener->CapturingAudio()) {
4131 array->AppendElement(ToSupports(window));
4132 }
4133 }
4134
4135 array.forget(aArray);
4136 return NS_OK;
4137}
4138
4139struct CaptureWindowStateData {
4140 uint16_t* mCamera;
4141 uint16_t* mMicrophone;
4142 uint16_t* mScreenShare;
4143 uint16_t* mWindowShare;
4144 uint16_t* mAppShare;
4145 uint16_t* mBrowserShare;
4146};
4147
4148NS_IMETHODIMPnsresult
4149MediaManager::MediaCaptureWindowState(
4150 nsIDOMWindow* aCapturedWindow, uint16_t* aCamera, uint16_t* aMicrophone,
4151 uint16_t* aScreen, uint16_t* aWindow, uint16_t* aBrowser,
4152 nsTArray<RefPtr<nsIMediaDevice>>& aDevices) {
4153 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/MediaManager.cpp", 4153); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4153); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4154
4155 CaptureState camera = CaptureState::Off;
4156 CaptureState microphone = CaptureState::Off;
4157 CaptureState screen = CaptureState::Off;
4158 CaptureState window = CaptureState::Off;
4159 CaptureState browser = CaptureState::Off;
4160 RefPtr<LocalMediaDeviceSetRefCnt> devices;
4161
4162 nsCOMPtr<nsPIDOMWindowInner> piWin = do_QueryInterface(aCapturedWindow);
4163 if (piWin) {
4164 if (RefPtr<GetUserMediaWindowListener> listener =
4165 GetWindowListener(piWin->WindowID())) {
4166 camera = listener->CapturingSource(MediaSourceEnum::Camera);
4167 microphone = listener->CapturingSource(MediaSourceEnum::Microphone);
4168 screen = listener->CapturingSource(MediaSourceEnum::Screen);
4169 window = listener->CapturingSource(MediaSourceEnum::Window);
4170 browser = listener->CapturingSource(MediaSourceEnum::Browser);
4171 devices = listener->GetDevices();
4172 }
4173 }
4174
4175 *aCamera = FromCaptureState(camera);
4176 *aMicrophone = FromCaptureState(microphone);
4177 *aScreen = FromCaptureState(screen);
4178 *aWindow = FromCaptureState(window);
4179 *aBrowser = FromCaptureState(browser);
4180 if (devices) {
4181 for (auto& device : *devices) {
4182 aDevices.AppendElement(device);
4183 }
4184 }
4185
4186 LOG("%s: window %" PRIu64"l" "u" " capturing %s %s %s %s %s", __FUNCTION__,
4187 piWin ? piWin->WindowID() : -1,
4188 *aCamera == nsIMediaManagerService::STATE_CAPTURE_ENABLED
4189 ? "camera (enabled)"
4190 : (*aCamera == nsIMediaManagerService::STATE_CAPTURE_DISABLED
4191 ? "camera (disabled)"
4192 : ""),
4193 *aMicrophone == nsIMediaManagerService::STATE_CAPTURE_ENABLED
4194 ? "microphone (enabled)"
4195 : (*aMicrophone == nsIMediaManagerService::STATE_CAPTURE_DISABLED
4196 ? "microphone (disabled)"
4197 : ""),
4198 *aScreen ? "screenshare" : "", *aWindow ? "windowshare" : "",
4199 *aBrowser ? "browsershare" : "");
4200
4201 return NS_OK;
4202}
4203
4204NS_IMETHODIMPnsresult
4205MediaManager::SanitizeDeviceIds(int64_t aSinceWhen) {
4206 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/MediaManager.cpp", 4206); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4206); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4207 LOG("%s: sinceWhen = %" PRId64"l" "d", __FUNCTION__, aSinceWhen);
4208
4209 media::SanitizeOriginKeys(aSinceWhen, false); // we fire and forget
4210 return NS_OK;
4211}
4212
4213void MediaManager::StopScreensharing(uint64_t aWindowID) {
4214 // We need to stop window/screensharing for all streams in this innerwindow.
4215
4216 if (RefPtr<GetUserMediaWindowListener> listener =
4217 GetWindowListener(aWindowID)) {
4218 listener->StopSharing();
4219 }
4220}
4221
4222bool MediaManager::IsActivelyCapturingOrHasAPermission(uint64_t aWindowId) {
4223 // Does page currently have a gUM stream active?
4224
4225 nsCOMPtr<nsIArray> array;
4226 GetActiveMediaCaptureWindows(getter_AddRefs(array));
4227 uint32_t len;
4228 array->GetLength(&len);
4229 for (uint32_t i = 0; i < len; i++) {
4230 nsCOMPtr<nsPIDOMWindowInner> win;
4231 array->QueryElementAt(i, NS_GET_IID(nsPIDOMWindowInner)(nsPIDOMWindowInner::kIID),
4232 getter_AddRefs(win));
4233 if (win && win->WindowID() == aWindowId) {
4234 return true;
4235 }
4236 }
4237
4238 // Or are persistent permissions (audio or video) granted?
4239
4240 return GetPersistentPermissions(aWindowId)
4241 .map([](auto&& aState) {
4242 return aState.mMicrophonePermission ==
4243 PersistentPermissionState::Allow ||
4244 aState.mCameraPermission == PersistentPermissionState::Allow;
4245 })
4246 .unwrapOr(false);
4247}
4248
4249DeviceListener::DeviceListener()
4250 : mStopped(false),
4251 mMainThreadCheck(nullptr),
4252 mPrincipalHandle(PRINCIPAL_HANDLE_NONEnullptr),
4253 mWindowListener(nullptr) {}
4254
4255void DeviceListener::Register(GetUserMediaWindowListener* aListener) {
4256 LOG("DeviceListener %p registering with window listener %p", this, aListener);
4257
4258 MOZ_ASSERT(aListener, "No listener")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aListener" " (" "No listener"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 4258)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "aListener" ") (" "No listener"
")"); do { MOZ_CrashSequence(__null, 4258); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4259 MOZ_ASSERT(!mWindowListener, "Already registered")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mWindowListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mWindowListener))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mWindowListener"
" (" "Already registered" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4259); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mWindowListener"
") (" "Already registered" ")"); do { MOZ_CrashSequence(__null
, 4259); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4260 MOZ_ASSERT(!Activated(), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!Activated())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!Activated()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!Activated()" " ("
"Already activated" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!Activated()"
") (" "Already activated" ")"); do { MOZ_CrashSequence(__null
, 4260); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4261
4262 mPrincipalHandle = aListener->GetPrincipalHandle();
4263 mWindowListener = aListener;
4264}
4265
4266void DeviceListener::Activate(RefPtr<LocalMediaDevice> aDevice,
4267 RefPtr<LocalTrackSource> aTrackSource,
4268 bool aStartMuted) {
4269 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4269); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4269); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4270
4271 LOG("DeviceListener %p activating %s device %p", this,
4272 dom::GetEnumString(aDevice->Kind()).get(), aDevice.get());
4273
4274 MOZ_ASSERT(!mStopped, "Cannot activate stopped device listener")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mStopped)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mStopped))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mStopped" " (" "Cannot activate stopped device listener"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 4274)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mStopped" ") (" "Cannot activate stopped device listener"
")"); do { MOZ_CrashSequence(__null, 4274); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4275 MOZ_ASSERT(!Activated(), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!Activated())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!Activated()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!Activated()" " ("
"Already activated" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!Activated()"
") (" "Already activated" ")"); do { MOZ_CrashSequence(__null
, 4275); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4276
4277 mMainThreadCheck = PR_GetCurrentThread();
4278 bool offWhileDisabled =
4279 (aDevice->GetMediaSource() == MediaSourceEnum::Microphone &&
4280 Preferences::GetBool(
4281 "media.getusermedia.microphone.off_while_disabled.enabled", true)) ||
4282 (aDevice->GetMediaSource() == MediaSourceEnum::Camera &&
4283 Preferences::GetBool(
4284 "media.getusermedia.camera.off_while_disabled.enabled", true));
4285
4286 if (MediaEventSource<void>* event = aDevice->Source()->CaptureEndedEvent()) {
4287 mCaptureEndedListener = event->Connect(AbstractThread::MainThread(), this,
4288 &DeviceListener::Stop);
4289 }
4290
4291 mDeviceState = MakeUnique<DeviceState>(
4292 std::move(aDevice), std::move(aTrackSource), offWhileDisabled);
4293 mDeviceState->mDeviceMuted = aStartMuted;
4294 if (aStartMuted) {
4295 mDeviceState->mTrackSource->Mute();
4296 }
4297}
4298
4299RefPtr<DeviceListener::DeviceListenerPromise>
4300DeviceListener::InitializeAsync() {
4301 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4301); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4302 MOZ_DIAGNOSTIC_ASSERT(!mStopped)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mStopped)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mStopped))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mStopped", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4302); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mStopped"
")"); do { MOZ_CrashSequence(__null, 4302); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4303
4304 return MediaManager::Dispatch<DeviceListenerPromise>(
4305 __func__,
4306 [principal = GetPrincipalHandle(), device = mDeviceState->mDevice,
4307 track = mDeviceState->mTrackSource->mTrack,
4308 deviceMuted = mDeviceState->mDeviceMuted](
4309 MozPromiseHolder<DeviceListenerPromise>& aHolder) {
4310 auto kind = device->Kind();
4311 device->SetTrack(track, principal);
4312 nsresult rv = deviceMuted ? NS_OK : device->Start();
4313 if (kind == MediaDeviceKind::Audioinput ||
4314 kind == MediaDeviceKind::Videoinput) {
4315 if ((rv == NS_ERROR_NOT_AVAILABLE &&
4316 kind == MediaDeviceKind::Audioinput) ||
4317 (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && kind == MediaDeviceKind::Videoinput)) {
4318 PR_Sleep(200);
4319 rv = device->Start();
4320 }
4321 if (rv == NS_ERROR_NOT_AVAILABLE &&
4322 kind == MediaDeviceKind::Audioinput) {
4323 nsCString log;
4324 log.AssignLiteral("Concurrent mic process limit.");
4325 aHolder.Reject(MakeRefPtr<MediaMgrError>(
4326 MediaMgrError::Name::NotReadableError,
4327 std::move(log)),
4328 __func__);
4329 return;
4330 }
4331 }
4332 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4333 nsCString log;
4334 log.AppendPrintf("Starting %s failed",
4335 dom::GetEnumString(kind).get());
4336 aHolder.Reject(
4337 MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError,
4338 std::move(log)),
4339 __func__);
4340 return;
4341 }
4342 LOG("started %s device %p", dom::GetEnumString(kind).get(),
4343 device.get());
4344 aHolder.Resolve(true, __func__);
4345 })
4346 ->Then(
4347 GetMainThreadSerialEventTarget(), __func__,
4348 [self = RefPtr<DeviceListener>(this), this]() {
4349 if (mStopped) {
4350 // We were shut down during the async init
4351 return DeviceListenerPromise::CreateAndResolve(true, __func__);
4352 }
4353
4354 MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mTrackEnabled)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDeviceState->mTrackEnabled)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDeviceState->mTrackEnabled
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mDeviceState->mTrackEnabled", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4354); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mTrackEnabled"
")"); do { MOZ_CrashSequence(__null, 4354); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4355 MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mDeviceEnabled)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDeviceState->mDeviceEnabled)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDeviceState->mDeviceEnabled
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mDeviceState->mDeviceEnabled", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4355); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mDeviceEnabled"
")"); do { MOZ_CrashSequence(__null, 4355); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4356 MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mStopped)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDeviceState->mStopped)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDeviceState->mStopped))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDeviceState->mStopped"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 4356); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mStopped" ")"
); do { MOZ_CrashSequence(__null, 4356); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4357
4358 mDeviceState->mDeviceEnabled = true;
4359 mDeviceState->mTrackEnabled = true;
4360 mDeviceState->mTrackEnabledTime = TimeStamp::Now();
4361 return DeviceListenerPromise::CreateAndResolve(true, __func__);
4362 },
4363 [self = RefPtr<DeviceListener>(this),
4364 this](const RefPtr<MediaMgrError>& aResult) {
4365 if (mStopped) {
4366 return DeviceListenerPromise::CreateAndReject(aResult, __func__);
4367 }
4368
4369 MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mTrackEnabled)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDeviceState->mTrackEnabled)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDeviceState->mTrackEnabled
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mDeviceState->mTrackEnabled", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4369); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mTrackEnabled"
")"); do { MOZ_CrashSequence(__null, 4369); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4370 MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mDeviceEnabled)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDeviceState->mDeviceEnabled)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDeviceState->mDeviceEnabled
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mDeviceState->mDeviceEnabled", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4370); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mDeviceEnabled"
")"); do { MOZ_CrashSequence(__null, 4370); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4371 MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mStopped)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDeviceState->mStopped)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDeviceState->mStopped))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDeviceState->mStopped"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 4371); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mStopped" ")"
); do { MOZ_CrashSequence(__null, 4371); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4372
4373 Stop();
4374 return DeviceListenerPromise::CreateAndReject(aResult, __func__);
4375 });
4376}
4377
4378void DeviceListener::Stop() {
4379 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4379); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4380
4381 if (mStopped) {
4382 return;
4383 }
4384 mStopped = true;
4385
4386 LOG("DeviceListener %p stopping", this);
4387
4388 if (mDeviceState) {
4389 mDeviceState->mDisableTimer->Cancel();
4390
4391 if (mDeviceState->mStopped) {
4392 // device already stopped.
4393 return;
4394 }
4395 mDeviceState->mStopped = true;
4396
4397 mDeviceState->mTrackSource->Stop();
4398
4399 MediaManager::Dispatch(NewTaskFrom([device = mDeviceState->mDevice]() {
4400 device->Stop();
4401 device->Deallocate();
4402 }));
4403
4404 mWindowListener->ChromeAffectingStateChanged();
4405 }
4406
4407 mCaptureEndedListener.DisconnectIfExists();
4408
4409 // Keep a strong ref to the removed window listener.
4410 RefPtr<GetUserMediaWindowListener> windowListener = mWindowListener;
4411 mWindowListener = nullptr;
4412 windowListener->Remove(this);
4413}
4414
4415void DeviceListener::GetSettings(MediaTrackSettings& aOutSettings) const {
4416 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4416); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4417 LocalMediaDevice* device = GetDevice();
4418 device->GetSettings(aOutSettings);
4419
4420 MediaSourceEnum mediaSource = device->GetMediaSource();
4421 if (mediaSource == MediaSourceEnum::Camera ||
4422 mediaSource == MediaSourceEnum::Microphone) {
4423 aOutSettings.mDeviceId.Construct(device->mID);
4424 aOutSettings.mGroupId.Construct(device->mGroupID);
4425 }
4426}
4427
4428void DeviceListener::GetCapabilities(
4429 MediaTrackCapabilities& aOutCapabilities) const {
4430 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4430); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4431 LocalMediaDevice* device = GetDevice();
4432 device->GetCapabilities(aOutCapabilities);
4433
4434 MediaSourceEnum mediaSource = device->GetMediaSource();
4435 if (mediaSource == MediaSourceEnum::Camera ||
4436 mediaSource == MediaSourceEnum::Microphone) {
4437 aOutCapabilities.mDeviceId.Construct(device->mID);
4438 aOutCapabilities.mGroupId.Construct(device->mGroupID);
4439 }
4440}
4441
4442auto DeviceListener::UpdateDevice(bool aOn) -> RefPtr<DeviceOperationPromise> {
4443 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/MediaManager.cpp", 4443); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4443); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4444 RefPtr<DeviceListener> self = this;
4445 DeviceState& state = *mDeviceState;
4446 return MediaManager::Dispatch<DeviceOperationPromise>(
4447 __func__,
4448 [self, device = state.mDevice,
4449 aOn](MozPromiseHolder<DeviceOperationPromise>& h) {
4450 LOG("Turning %s device (%s)", aOn ? "on" : "off",
4451 NS_ConvertUTF16toUTF8(device->mName).get());
4452 h.Resolve(aOn ? device->Start() : device->Stop(), __func__);
4453 })
4454 ->Then(
4455 GetMainThreadSerialEventTarget(), __func__,
4456 [self, this, &state, aOn](nsresult aResult) {
4457 if (state.mStopped) {
4458 // Device was stopped on main thread during the operation. Done.
4459 return DeviceOperationPromise::CreateAndResolve(aResult,
4460 __func__);
4461 }
4462 LOG("DeviceListener %p turning %s %s input device %s", this,
4463 aOn ? "on" : "off",
4464 dom::GetEnumString(GetDevice()->Kind()).get(),
4465 NS_SUCCEEDED(aResult)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResult)), 1))) ? "succeeded" : "failed");
4466
4467 if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0))) && aResult != NS_ERROR_ABORT) {
4468 // This path handles errors from starting or stopping the
4469 // device. NS_ERROR_ABORT are for cases where *we* aborted. They
4470 // need graceful handling.
4471 if (aOn) {
4472 // Starting the device failed. Stopping the track here will
4473 // make the MediaStreamTrack end after a pass through the
4474 // MediaTrackGraph.
4475 Stop();
4476 } else {
4477 // Stopping the device failed. This is odd, but not fatal.
4478 MOZ_ASSERT_UNREACHABLE("The device should be stoppable")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: "
"The device should be stoppable" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "The device should be stoppable" ")"
); do { MOZ_CrashSequence(__null, 4478); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4479 }
4480 }
4481 return DeviceOperationPromise::CreateAndResolve(aResult, __func__);
4482 },
4483 []() {
4484 MOZ_ASSERT_UNREACHABLE("Unexpected and unhandled reject")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unexpected and unhandled reject" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject"
")"); do { MOZ_CrashSequence(__null, 4484); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4485 return DeviceOperationPromise::CreateAndReject(false, __func__);
4486 });
4487}
4488
4489void DeviceListener::SetDeviceEnabled(bool aEnable) {
4490 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4490); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4491 MOZ_ASSERT(Activated(), "No device to set enabled state for")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(Activated())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(Activated()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("Activated()" " ("
"No device to set enabled state for" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4491); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Activated()"
") (" "No device to set enabled state for" ")"); do { MOZ_CrashSequence
(__null, 4491); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4492
4493 DeviceState& state = *mDeviceState;
4494
4495 LOG("DeviceListener %p %s %s device", this,
4496 aEnable ? "enabling" : "disabling",
4497 dom::GetEnumString(GetDevice()->Kind()).get());
4498
4499 state.mTrackEnabled = aEnable;
4500
4501 if (state.mStopped) {
4502 // Device terminally stopped. Updating device state is pointless.
4503 return;
4504 }
4505
4506 if (state.mOperationInProgress) {
4507 // If a timer is in progress, it needs to be canceled now so the next
4508 // DisableTrack() gets a fresh start. Canceling will trigger another
4509 // operation.
4510 state.mDisableTimer->Cancel();
4511 return;
4512 }
4513
4514 if (state.mDeviceEnabled == aEnable) {
4515 // Device is already in the desired state.
4516 return;
4517 }
4518
4519 // All paths from here on must end in setting
4520 // `state.mOperationInProgress` to false.
4521 state.mOperationInProgress = true;
4522
4523 RefPtr<MediaTimerPromise> timerPromise;
4524 if (aEnable) {
4525 timerPromise = MediaTimerPromise::CreateAndResolve(true, __func__);
4526 state.mTrackEnabledTime = TimeStamp::Now();
4527 } else {
4528 const TimeDuration maxDelay =
4529 TimeDuration::FromMilliseconds(Preferences::GetUint(
4530 GetDevice()->Kind() == MediaDeviceKind::Audioinput
4531 ? "media.getusermedia.microphone.off_while_disabled.delay_ms"
4532 : "media.getusermedia.camera.off_while_disabled.delay_ms",
4533 3000));
4534 const TimeDuration durationEnabled =
4535 TimeStamp::Now() - state.mTrackEnabledTime;
4536 const TimeDuration delay = TimeDuration::Max(
4537 TimeDuration::FromMilliseconds(0), maxDelay - durationEnabled);
4538 timerPromise = state.mDisableTimer->WaitFor(delay, __func__);
4539 }
4540
4541 RefPtr<DeviceListener> self = this;
4542 timerPromise
4543 ->Then(
4544 GetMainThreadSerialEventTarget(), __func__,
4545 [self, this, &state, aEnable]() mutable {
4546 MOZ_ASSERT(state.mDeviceEnabled != aEnable,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(state.mDeviceEnabled != aEnable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled != aEnable
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"state.mDeviceEnabled != aEnable" " (" "Device operation hasn't started"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 4547)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled != aEnable"
") (" "Device operation hasn't started" ")"); do { MOZ_CrashSequence
(__null, 4547); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4547 "Device operation hasn't started")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(state.mDeviceEnabled != aEnable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled != aEnable
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"state.mDeviceEnabled != aEnable" " (" "Device operation hasn't started"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 4547)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled != aEnable"
") (" "Device operation hasn't started" ")"); do { MOZ_CrashSequence
(__null, 4547); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4548 MOZ_ASSERT(state.mOperationInProgress,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(state.mOperationInProgress)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(state.mOperationInProgress))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mOperationInProgress"
" (" "It's our responsibility to reset the inProgress state"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 4549)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mOperationInProgress"
") (" "It's our responsibility to reset the inProgress state"
")"); do { MOZ_CrashSequence(__null, 4549); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4549 "It's our responsibility to reset the inProgress state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(state.mOperationInProgress)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(state.mOperationInProgress))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mOperationInProgress"
" (" "It's our responsibility to reset the inProgress state"
")", "/root/firefox-clang/dom/media/MediaManager.cpp", 4549)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mOperationInProgress"
") (" "It's our responsibility to reset the inProgress state"
")"); do { MOZ_CrashSequence(__null, 4549); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4550
4551 LOG("DeviceListener %p %s %s device - starting device operation",
4552 this, aEnable ? "enabling" : "disabling",
4553 dom::GetEnumString(GetDevice()->Kind()).get());
4554
4555 if (state.mStopped) {
4556 // Source was stopped between timer resolving and this runnable.
4557 return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT,
4558 __func__);
4559 }
4560
4561 state.mDeviceEnabled = aEnable;
4562
4563 if (mWindowListener) {
4564 mWindowListener->ChromeAffectingStateChanged();
4565 }
4566 if (!state.mOffWhileDisabled || state.mDeviceMuted) {
4567 // If the feature to turn a device off while disabled is itself
4568 // disabled, or the device is currently user agent muted, then
4569 // we shortcut the device operation and tell the
4570 // ux-updating code that everything went fine.
4571 return DeviceOperationPromise::CreateAndResolve(NS_OK, __func__);
4572 }
4573 return UpdateDevice(aEnable);
4574 },
4575 []() {
4576 // Timer was canceled by us. We signal this with NS_ERROR_ABORT.
4577 return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT,
4578 __func__);
4579 })
4580 ->Then(
4581 GetMainThreadSerialEventTarget(), __func__,
4582 [self, this, &state, aEnable](nsresult aResult) mutable {
4583 MOZ_ASSERT_IF(aResult != NS_ERROR_ABORT,do { if (aResult != NS_ERROR_ABORT) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(state.mDeviceEnabled
== aEnable)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(state.mDeviceEnabled == aEnable))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mDeviceEnabled == aEnable"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 4584); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "state.mDeviceEnabled == aEnable" ")"); do {
MOZ_CrashSequence(__null, 4584); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
4584 state.mDeviceEnabled == aEnable)do { if (aResult != NS_ERROR_ABORT) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(state.mDeviceEnabled
== aEnable)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(state.mDeviceEnabled == aEnable))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mDeviceEnabled == aEnable"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 4584); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "state.mDeviceEnabled == aEnable" ")"); do {
MOZ_CrashSequence(__null, 4584); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
4585 MOZ_ASSERT(state.mOperationInProgress)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(state.mOperationInProgress)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(state.mOperationInProgress))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mOperationInProgress"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 4585); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "state.mOperationInProgress" ")"); do { MOZ_CrashSequence
(__null, 4585); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4586 state.mOperationInProgress = false;
4587
4588 if (state.mStopped) {
4589 // Device was stopped on main thread during the operation.
4590 // Nothing to do.
4591 return;
4592 }
4593
4594 if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0))) && aResult != NS_ERROR_ABORT && !aEnable) {
4595 // To keep our internal state sane in this case, we disallow
4596 // future stops due to disable.
4597 state.mOffWhileDisabled = false;
4598 return;
4599 }
4600
4601 // This path is for a device operation aResult that was success or
4602 // NS_ERROR_ABORT (*we* canceled the operation).
4603 // At this point we have to follow up on the intended state, i.e.,
4604 // update the device state if the track state changed in the
4605 // meantime.
4606
4607 if (state.mTrackEnabled != state.mDeviceEnabled) {
4608 // Track state changed during this operation. We'll start over.
4609 SetDeviceEnabled(state.mTrackEnabled);
4610 }
4611 },
4612 []() { MOZ_ASSERT_UNREACHABLE("Unexpected and unhandled reject")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unexpected and unhandled reject" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject"
")"); do { MOZ_CrashSequence(__null, 4612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; });
4613}
4614
4615void DeviceListener::SetDeviceMuted(bool aMute) {
4616 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4616); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4616); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4617 MOZ_ASSERT(Activated(), "No device to set muted state for")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(Activated())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(Activated()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("Activated()" " ("
"No device to set muted state for" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Activated()"
") (" "No device to set muted state for" ")"); do { MOZ_CrashSequence
(__null, 4617); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4618
4619 DeviceState& state = *mDeviceState;
4620
4621 LOG("DeviceListener %p %s %s device", this, aMute ? "muting" : "unmuting",
4622 dom::GetEnumString(GetDevice()->Kind()).get());
4623
4624 if (state.mStopped) {
4625 // Device terminally stopped. Updating device state is pointless.
4626 return;
4627 }
4628
4629 if (state.mDeviceMuted == aMute) {
4630 // Device is already in the desired state.
4631 return;
4632 }
4633
4634 LOG("DeviceListener %p %s %s device - starting device operation", this,
4635 aMute ? "muting" : "unmuting",
4636 dom::GetEnumString(GetDevice()->Kind()).get());
4637
4638 state.mDeviceMuted = aMute;
4639
4640 if (mWindowListener) {
4641 mWindowListener->ChromeAffectingStateChanged();
4642 }
4643 // Update trackSource to fire mute/unmute events on all its tracks
4644 if (aMute) {
4645 state.mTrackSource->Mute();
4646 } else {
4647 state.mTrackSource->Unmute();
4648 }
4649 if (!state.mOffWhileDisabled || !state.mDeviceEnabled) {
4650 // If the pref to turn the underlying device is itself off, or the device
4651 // is already off, it's unecessary to do anything else.
4652 return;
4653 }
4654 UpdateDevice(!aMute);
4655}
4656
4657void DeviceListener::MuteOrUnmuteCamera(bool aMute) {
4658 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/MediaManager.cpp", 4658); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4658); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4659
4660 if (mStopped) {
4661 return;
4662 }
4663
4664 MOZ_RELEASE_ASSERT(mWindowListener)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindowListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWindowListener))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mWindowListener"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 4664); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "mWindowListener" ")"); do { MOZ_CrashSequence
(__null, 4664); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4665 LOG("DeviceListener %p MuteOrUnmuteCamera: %s", this,
4666 aMute ? "mute" : "unmute");
4667
4668 if (GetDevice() &&
4669 (GetDevice()->GetMediaSource() == MediaSourceEnum::Camera)) {
4670 SetDeviceMuted(aMute);
4671 }
4672}
4673
4674void DeviceListener::MuteOrUnmuteMicrophone(bool aMute) {
4675 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/MediaManager.cpp", 4675); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4675); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4676
4677 if (mStopped) {
4678 return;
4679 }
4680
4681 MOZ_RELEASE_ASSERT(mWindowListener)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWindowListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWindowListener))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mWindowListener"
, "/root/firefox-clang/dom/media/MediaManager.cpp", 4681); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "mWindowListener" ")"); do { MOZ_CrashSequence
(__null, 4681); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4682 LOG("DeviceListener %p MuteOrUnmuteMicrophone: %s", this,
4683 aMute ? "mute" : "unmute");
4684
4685 if (GetDevice() &&
4686 (GetDevice()->GetMediaSource() == MediaSourceEnum::Microphone)) {
4687 SetDeviceMuted(aMute);
4688 }
4689}
4690
4691bool DeviceListener::CapturingVideo() const {
4692 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/MediaManager.cpp", 4692); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4692); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4693 return Activated() && mDeviceState && !mDeviceState->mStopped &&
4694 MediaEngineSource::IsVideo(GetDevice()->GetMediaSource()) &&
4695 (!GetDevice()->IsFake() ||
4696 Preferences::GetBool("media.navigator.permission.fake"));
4697}
4698
4699bool DeviceListener::CapturingAudio() const {
4700 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/MediaManager.cpp", 4700); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4700); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4701 return Activated() && mDeviceState && !mDeviceState->mStopped &&
4702 MediaEngineSource::IsAudio(GetDevice()->GetMediaSource()) &&
4703 (!GetDevice()->IsFake() ||
4704 Preferences::GetBool("media.navigator.permission.fake"));
4705}
4706
4707CaptureState DeviceListener::CapturingSource(MediaSourceEnum aSource) const {
4708 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/MediaManager.cpp", 4708); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4708); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4709 if (GetDevice()->GetMediaSource() != aSource) {
4710 // This DeviceListener doesn't capture a matching source
4711 return CaptureState::Off;
4712 }
4713
4714 if (mDeviceState->mStopped) {
4715 // The source is a match but has been permanently stopped
4716 return CaptureState::Off;
4717 }
4718
4719 if ((aSource == MediaSourceEnum::Camera ||
4720 aSource == MediaSourceEnum::Microphone) &&
4721 GetDevice()->IsFake() &&
4722 !Preferences::GetBool("media.navigator.permission.fake")) {
4723 // Fake Camera and Microphone only count if there is no fake permission
4724 return CaptureState::Off;
4725 }
4726
4727 // Source is a match and is active and unmuted
4728
4729 if (mDeviceState->mDeviceEnabled && !mDeviceState->mDeviceMuted) {
4730 return CaptureState::Enabled;
4731 }
4732
4733 return CaptureState::Disabled;
4734}
4735
4736RefPtr<DeviceListener::DeviceListenerPromise> DeviceListener::ApplyConstraints(
4737 const MediaTrackConstraints& aConstraints, CallerType aCallerType) {
4738 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/MediaManager.cpp", 4738); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4738); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4739
4740 if (mStopped || mDeviceState->mStopped) {
4741 LOG("DeviceListener %p %s device applyConstraints, but device is stopped",
4742 this, dom::GetEnumString(GetDevice()->Kind()).get());
4743 return DeviceListenerPromise::CreateAndResolve(false, __func__);
4744 }
4745
4746 MediaManager* mgr = MediaManager::GetIfExists();
4747 if (!mgr) {
4748 return DeviceListenerPromise::CreateAndResolve(false, __func__);
4749 }
4750
4751 return MediaManager::Dispatch<DeviceListenerPromise>(
4752 __func__,
4753 [device = mDeviceState->mDevice, aConstraints, prefs = mgr->mPrefs,
4754 aCallerType](MozPromiseHolder<DeviceListenerPromise>& aHolder) mutable {
4755 MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("MediaManager::IsInMediaThread()", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()"
")"); do { MOZ_CrashSequence(__null, 4755); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4756 MediaManager* mgr = MediaManager::GetIfExists();
4757 MOZ_RELEASE_ASSERT(mgr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mgr)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mgr))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mgr", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4757); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mgr"
")"); do { MOZ_CrashSequence(__null, 4757); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // Must exist while media thread is alive
4758 const char* badConstraint = nullptr;
4759 nsresult rv =
4760 device->Reconfigure(aConstraints, mgr->mPrefs, &badConstraint);
4761 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4762 if (rv == NS_ERROR_INVALID_ARG) {
4763 // Reconfigure failed due to constraints
4764 if (!badConstraint) {
4765 nsTArray<RefPtr<LocalMediaDevice>> devices;
4766 devices.AppendElement(device);
4767 badConstraint = MediaConstraintsHelper::SelectSettings(
4768 NormalizedConstraints(aConstraints), prefs, devices,
4769 aCallerType);
4770 }
4771 } else {
4772 // Unexpected. ApplyConstraints* cannot fail with any other error.
4773 badConstraint = "";
4774 LOG("ApplyConstraints-Task: Unexpected fail %" PRIx32"x",
4775 static_cast<uint32_t>(rv));
4776 }
4777
4778 aHolder.Reject(MakeRefPtr<MediaMgrError>(
4779 MediaMgrError::Name::OverconstrainedError, "",
4780 NS_ConvertASCIItoUTF16(badConstraint)),
4781 __func__);
4782 return;
4783 }
4784 // Reconfigure was successful
4785 aHolder.Resolve(false, __func__);
4786 });
4787}
4788
4789PrincipalHandle DeviceListener::GetPrincipalHandle() const {
4790 return mPrincipalHandle;
4791}
4792
4793void GetUserMediaWindowListener::StopSharing() {
4794 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4794); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4795
4796 for (auto& l : mActiveListeners.Clone()) {
4797 MediaSourceEnum source = l->GetDevice()->GetMediaSource();
4798 if (source == MediaSourceEnum::Screen ||
4799 source == MediaSourceEnum::Window ||
4800 source == MediaSourceEnum::AudioCapture ||
4801 source == MediaSourceEnum::Browser) {
4802 l->Stop();
4803 }
4804 }
4805}
4806
4807void GetUserMediaWindowListener::StopRawID(const nsString& removedDeviceID) {
4808 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4808); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4809
4810 for (auto& l : mActiveListeners.Clone()) {
4811 if (removedDeviceID.Equals(l->GetDevice()->RawID())) {
4812 l->Stop();
4813 }
4814 }
4815}
4816
4817void GetUserMediaWindowListener::MuteOrUnmuteCameras(bool aMute) {
4818 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4818); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4819
4820 if (mCamerasAreMuted == aMute) {
4821 return;
4822 }
4823 mCamerasAreMuted = aMute;
4824
4825 for (auto& l : mActiveListeners.Clone()) {
4826 if (l->GetDevice()->Kind() == MediaDeviceKind::Videoinput) {
4827 l->MuteOrUnmuteCamera(aMute);
4828 }
4829 }
4830}
4831
4832void GetUserMediaWindowListener::MuteOrUnmuteMicrophones(bool aMute) {
4833 MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Only call on main thread" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Only call on main thread" ")"); do { MOZ_CrashSequence
(__null, 4833); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4834
4835 if (mMicrophonesAreMuted == aMute) {
4836 return;
4837 }
4838 mMicrophonesAreMuted = aMute;
4839
4840 for (auto& l : mActiveListeners.Clone()) {
4841 if (l->GetDevice()->Kind() == MediaDeviceKind::Audioinput) {
4842 l->MuteOrUnmuteMicrophone(aMute);
4843 }
4844 }
4845}
4846
4847void GetUserMediaWindowListener::ChromeAffectingStateChanged() {
4848 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/MediaManager.cpp", 4848); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4848); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4849
4850 // We wait until stable state before notifying chrome so chrome only does
4851 // one update if more updates happen in this event loop.
4852
4853 if (mChromeNotificationTaskPosted) {
4854 return;
4855 }
4856
4857 nsCOMPtr<nsIRunnable> runnable =
4858 NewRunnableMethod("GetUserMediaWindowListener::NotifyChrome", this,
4859 &GetUserMediaWindowListener::NotifyChrome);
4860 nsContentUtils::RunInStableState(runnable.forget());
4861 mChromeNotificationTaskPosted = true;
4862}
4863
4864void GetUserMediaWindowListener::NotifyChrome() {
4865 MOZ_ASSERT(mChromeNotificationTaskPosted)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mChromeNotificationTaskPosted)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mChromeNotificationTaskPosted
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mChromeNotificationTaskPosted", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4865); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChromeNotificationTaskPosted"
")"); do { MOZ_CrashSequence(__null, 4865); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4866 mChromeNotificationTaskPosted = false;
4867
4868 NS_DispatchToMainThread(NS_NewRunnableFunction(
4869 "MediaManager::NotifyChrome", [windowID = mWindowID]() {
4870 auto* window = nsGlobalWindowInner::GetInnerWindowWithId(windowID);
4871 if (!window) {
4872 MOZ_ASSERT_UNREACHABLE("Should have window")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: "
"Should have window" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4872); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Should have window" ")"); do { MOZ_CrashSequence
(__null, 4872); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4873 return;
4874 }
4875
4876 nsresult rv = MediaManager::NotifyRecordingStatusChange(window);
4877 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4878 MOZ_ASSERT_UNREACHABLE("Should be able to notify chrome")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: "
"Should be able to notify chrome" ")", "/root/firefox-clang/dom/media/MediaManager.cpp"
, 4878); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Should be able to notify chrome"
")"); do { MOZ_CrashSequence(__null, 4878); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4879 return;
4880 }
4881 }));
4882}
4883
4884#undef LOG
4885
4886} // namespace mozilla