Bug Summary

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