Bug Summary

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