Bug Summary

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