Bug Summary

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