File: | var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp |
Warning: | line 2874, column 12 Value stored to 'rv' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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. |
85 | template <class WebIDLCallbackT, class XPCOMCallbackT> |
86 | class 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 | |
149 | namespace mozilla { |
150 | |
151 | LazyLogModule 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 | |
154 | class GetUserMediaStreamTask; |
155 | class LocalTrackSource; |
156 | class SelectAudioOutputTask; |
157 | |
158 | using camera::CamerasAccessStatus; |
159 | using dom::BFCacheStatus; |
160 | using dom::CallerType; |
161 | using dom::ConstrainDOMStringParameters; |
162 | using dom::ConstrainDoubleRange; |
163 | using dom::ConstrainLongRange; |
164 | using dom::DisplayMediaStreamConstraints; |
165 | using dom::Document; |
166 | using dom::Element; |
167 | using dom::FeaturePolicyUtils; |
168 | using dom::File; |
169 | using dom::GetUserMediaRequest; |
170 | using dom::MediaDeviceKind; |
171 | using dom::MediaDevices; |
172 | using dom::MediaSourceEnum; |
173 | using dom::MediaStreamConstraints; |
174 | using dom::MediaStreamError; |
175 | using dom::MediaStreamTrack; |
176 | using dom::MediaStreamTrackSource; |
177 | using dom::MediaTrackCapabilities; |
178 | using dom::MediaTrackConstraints; |
179 | using dom::MediaTrackConstraintSet; |
180 | using dom::MediaTrackSettings; |
181 | using dom::OwningBooleanOrMediaTrackConstraints; |
182 | using dom::OwningStringOrStringSequence; |
183 | using dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters; |
184 | using dom::Promise; |
185 | using dom::Sequence; |
186 | using dom::UserActivation; |
187 | using dom::WindowGlobalChild; |
188 | using ConstDeviceSetPromise = MediaManager::ConstDeviceSetPromise; |
189 | using DeviceSetPromise = MediaManager::DeviceSetPromise; |
190 | using LocalDevicePromise = MediaManager::LocalDevicePromise; |
191 | using LocalDeviceSetPromise = MediaManager::LocalDeviceSetPromise; |
192 | using LocalMediaDeviceSetRefCnt = MediaManager::LocalMediaDeviceSetRefCnt; |
193 | using MediaDeviceSetRefCnt = MediaManager::MediaDeviceSetRefCnt; |
194 | using media::NewRunnableFrom; |
195 | using media::NewTaskFrom; |
196 | using media::Refcountable; |
197 | |
198 | // Whether main thread actions of MediaManager shutdown (except for clearing |
199 | // of sSingleton) have completed. |
200 | static bool sHasMainThreadShutdown; |
201 | |
202 | struct DeviceState { |
203 | DeviceState(RefPtr<LocalMediaDevice> aDevice, |
204 | RefPtr<LocalTrackSource> aTrackSource, bool aOffWhileDisabled) |
205 | : mOffWhileDisabled(aOffWhileDisabled), |
206 | mDevice(std::move(aDevice)), |
207 | mTrackSource(std::move(aTrackSource)) { |
208 | MOZ_ASSERT(mDevice)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mDevice)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mDevice))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mDevice", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDevice" ")" ); do { *((volatile int*)__null) = 208; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
209 | MOZ_ASSERT(mTrackSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mTrackSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mTrackSource))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mTrackSource", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTrackSource" ")"); do { *((volatile int*)__null) = 209; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
210 | } |
211 | |
212 | // true if we have stopped mDevice, this is a terminal state. |
213 | // MainThread only. |
214 | bool mStopped = false; |
215 | |
216 | // true if mDevice is currently enabled. |
217 | // A device must be both enabled and unmuted to be turned on and capturing. |
218 | // MainThread only. |
219 | bool mDeviceEnabled = false; |
220 | |
221 | // true if mDevice is currently muted. |
222 | // A device that is either muted or disabled is turned off and not capturing. |
223 | // MainThread only. |
224 | bool mDeviceMuted; |
225 | |
226 | // true if the application has currently enabled mDevice. |
227 | // MainThread only. |
228 | bool mTrackEnabled = false; |
229 | |
230 | // Time when the application last enabled mDevice. |
231 | // MainThread only. |
232 | TimeStamp mTrackEnabledTime; |
233 | |
234 | // true if an operation to Start() or Stop() mDevice has been dispatched to |
235 | // the media thread and is not finished yet. |
236 | // MainThread only. |
237 | bool mOperationInProgress = false; |
238 | |
239 | // true if we are allowed to turn off the underlying source while all tracks |
240 | // are disabled. Only affects disabling; always turns off on user-agent mute. |
241 | // MainThread only. |
242 | bool mOffWhileDisabled = false; |
243 | |
244 | // Timer triggered by a MediaStreamTrackSource signaling that all tracks got |
245 | // disabled. When the timer fires we initiate Stop()ing mDevice. |
246 | // If set we allow dynamically stopping and starting mDevice. |
247 | // Any thread. |
248 | const RefPtr<MediaTimer<TimeStamp>> mDisableTimer = |
249 | new MediaTimer<TimeStamp>(); |
250 | |
251 | // The underlying device we keep state for. Always non-null. |
252 | // Threadsafe access, but see method declarations for individual constraints. |
253 | const RefPtr<LocalMediaDevice> mDevice; |
254 | |
255 | // The MediaStreamTrackSource for any tracks (original and clones) originating |
256 | // from this device. Always non-null. Threadsafe access, but see method |
257 | // declarations for individual constraints. |
258 | const RefPtr<LocalTrackSource> mTrackSource; |
259 | }; |
260 | |
261 | /** |
262 | * This mimics the capture state from nsIMediaManagerService. |
263 | */ |
264 | enum class CaptureState : uint16_t { |
265 | Off = nsIMediaManagerService::STATE_NOCAPTURE, |
266 | Enabled = nsIMediaManagerService::STATE_CAPTURE_ENABLED, |
267 | Disabled = nsIMediaManagerService::STATE_CAPTURE_DISABLED, |
268 | }; |
269 | |
270 | static CaptureState CombineCaptureState(CaptureState aFirst, |
271 | CaptureState aSecond) { |
272 | if (aFirst == CaptureState::Enabled || aSecond == CaptureState::Enabled) { |
273 | return CaptureState::Enabled; |
274 | } |
275 | if (aFirst == CaptureState::Disabled || aSecond == CaptureState::Disabled) { |
276 | return CaptureState::Disabled; |
277 | } |
278 | MOZ_ASSERT(aFirst == CaptureState::Off)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aFirst == CaptureState::Off)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aFirst == CaptureState::Off) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aFirst == CaptureState::Off" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFirst == CaptureState::Off" ")"); do { *((volatile int*)__null) = 278; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
279 | MOZ_ASSERT(aSecond == CaptureState::Off)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSecond == CaptureState::Off)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aSecond == CaptureState::Off ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aSecond == CaptureState::Off", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSecond == CaptureState::Off" ")"); do { *((volatile int*)__null) = 279; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
280 | return CaptureState::Off; |
281 | } |
282 | |
283 | static uint16_t FromCaptureState(CaptureState aState) { |
284 | MOZ_ASSERT(aState == CaptureState::Off || aState == CaptureState::Enabled ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aState == CaptureState::Off || aState == CaptureState ::Enabled || aState == CaptureState::Disabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 285); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled" ")"); do { *((volatile int*)__null) = 285; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
285 | aState == CaptureState::Disabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aState == CaptureState::Off || aState == CaptureState ::Enabled || aState == CaptureState::Disabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 285); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled" ")"); do { *((volatile int*)__null) = 285; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
286 | return static_cast<uint16_t>(aState); |
287 | } |
288 | |
289 | void MediaManager::CallOnError(GetUserMediaErrorCallback& aCallback, |
290 | MediaStreamError& aError) { |
291 | aCallback.Call(aError); |
292 | } |
293 | |
294 | void MediaManager::CallOnSuccess(GetUserMediaSuccessCallback& aCallback, |
295 | DOMMediaStream& aStream) { |
296 | aCallback.Call(aStream); |
297 | } |
298 | |
299 | enum class PersistentPermissionState : uint32_t { |
300 | Unknown = nsIPermissionManager::UNKNOWN_ACTION, |
301 | Allow = nsIPermissionManager::ALLOW_ACTION, |
302 | Deny = nsIPermissionManager::DENY_ACTION, |
303 | Prompt = nsIPermissionManager::PROMPT_ACTION, |
304 | }; |
305 | |
306 | static PersistentPermissionState CheckPermission( |
307 | PersistentPermissionState aPermission) { |
308 | switch (aPermission) { |
309 | case PersistentPermissionState::Unknown: |
310 | case PersistentPermissionState::Allow: |
311 | case PersistentPermissionState::Deny: |
312 | case PersistentPermissionState::Prompt: |
313 | return aPermission; |
314 | } |
315 | MOZ_CRASH("Unexpected permission value")do { do { } while (false); MOZ_ReportCrash("" "Unexpected permission value" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 315); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected permission value" ")"); do { *((volatile int*)__null) = 315; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
316 | } |
317 | |
318 | struct WindowPersistentPermissionState { |
319 | PersistentPermissionState mCameraPermission; |
320 | PersistentPermissionState mMicrophonePermission; |
321 | }; |
322 | |
323 | static Result<WindowPersistentPermissionState, nsresult> |
324 | GetPersistentPermissions(uint64_t aWindowId) { |
325 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowId); |
326 | if (NS_WARN_IF(!window)NS_warn_if_impl(!window, "!window", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 326) || NS_WARN_IF(!window->GetPrincipal())NS_warn_if_impl(!window->GetPrincipal(), "!window->GetPrincipal()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 326)) { |
327 | return Err(NS_ERROR_INVALID_ARG); |
328 | } |
329 | |
330 | Document* doc = window->GetExtantDoc(); |
331 | if (NS_WARN_IF(!doc)NS_warn_if_impl(!doc, "!doc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 331)) { |
332 | return Err(NS_ERROR_INVALID_ARG); |
333 | } |
334 | |
335 | nsIPrincipal* principal = window->GetPrincipal(); |
336 | if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 336)) { |
337 | return Err(NS_ERROR_INVALID_ARG); |
338 | } |
339 | |
340 | nsresult rv; |
341 | RefPtr<PermissionDelegateHandler> permDelegate = |
342 | doc->GetPermissionDelegateHandler(); |
343 | if (NS_WARN_IF(!permDelegate)NS_warn_if_impl(!permDelegate, "!permDelegate", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 343)) { |
344 | return Err(NS_ERROR_INVALID_ARG); |
345 | } |
346 | |
347 | uint32_t audio = nsIPermissionManager::UNKNOWN_ACTION; |
348 | uint32_t video = nsIPermissionManager::UNKNOWN_ACTION; |
349 | { |
350 | rv = permDelegate->GetPermission("microphone"_ns, &audio, true); |
351 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 351)) { |
352 | return Err(rv); |
353 | } |
354 | rv = permDelegate->GetPermission("camera"_ns, &video, true); |
355 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 355)) { |
356 | return Err(rv); |
357 | } |
358 | } |
359 | |
360 | return WindowPersistentPermissionState{ |
361 | CheckPermission(static_cast<PersistentPermissionState>(video)), |
362 | CheckPermission(static_cast<PersistentPermissionState>(audio))}; |
363 | } |
364 | |
365 | /** |
366 | * DeviceListener has threadsafe refcounting for use across the main, media and |
367 | * MTG threads. But it has a non-threadsafe SupportsWeakPtr for WeakPtr usage |
368 | * only from main thread, to ensure that garbage- and cycle-collected objects |
369 | * don't hold a reference to it during late shutdown. |
370 | */ |
371 | class DeviceListener : public SupportsWeakPtr { |
372 | public: |
373 | typedef MozPromise<bool /* aIgnored */, RefPtr<MediaMgrError>, true> |
374 | DeviceListenerPromise; |
375 | |
376 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<DeviceListener>, "Reference-counted class " "DeviceListener" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 377; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("DeviceListener"), (uint32_t)(sizeof(*this))); return (nsrefcnt)count; } MozExternalRefCountType Release(void) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 377 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("DeviceListener")); if (count == 0) { ::mozilla::detail ::ProxyDeleteVoid( "ProxyDelete " "DeviceListener", ::mozilla ::GetMainThreadSerialEventTarget(), this, [](void* self) { delete static_cast<DeviceListener*>(self); }); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type; protected : ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
377 | DeviceListener)public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<DeviceListener>, "Reference-counted class " "DeviceListener" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 377; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("DeviceListener"), (uint32_t)(sizeof(*this))); return (nsrefcnt)count; } MozExternalRefCountType Release(void) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 377 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("DeviceListener")); if (count == 0) { ::mozilla::detail ::ProxyDeleteVoid( "ProxyDelete " "DeviceListener", ::mozilla ::GetMainThreadSerialEventTarget(), this, [](void* self) { delete static_cast<DeviceListener*>(self); }); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type; protected : ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
378 | |
379 | DeviceListener(); |
380 | |
381 | /** |
382 | * Registers this device listener as belonging to the given window listener. |
383 | * Stop() must be called on registered DeviceListeners before destruction. |
384 | */ |
385 | void Register(GetUserMediaWindowListener* aListener); |
386 | |
387 | /** |
388 | * Marks this listener as active and creates the internal device state. |
389 | */ |
390 | void Activate(RefPtr<LocalMediaDevice> aDevice, |
391 | RefPtr<LocalTrackSource> aTrackSource, bool aStartMuted); |
392 | |
393 | /** |
394 | * Posts a task to initialize and start the associated device. |
395 | */ |
396 | RefPtr<DeviceListenerPromise> InitializeAsync(); |
397 | |
398 | /** |
399 | * Posts a task to stop the device associated with this DeviceListener and |
400 | * notifies the associated window listener that a track was stopped. |
401 | * |
402 | * This will also clean up the weak reference to the associated window |
403 | * listener, and tell the window listener to remove its hard reference to this |
404 | * DeviceListener, so any caller will need to keep its own hard ref. |
405 | */ |
406 | void Stop(); |
407 | |
408 | /** |
409 | * Gets the main thread MediaTrackSettings from the MediaEngineSource |
410 | * associated with aTrack. |
411 | */ |
412 | void GetSettings(MediaTrackSettings& aOutSettings) const; |
413 | |
414 | /** |
415 | * Gets the main thread MediaTrackCapabilities from the MediaEngineSource |
416 | * associated with aTrack. |
417 | */ |
418 | void GetCapabilities(MediaTrackCapabilities& aOutCapabilities) const; |
419 | |
420 | /** |
421 | * Posts a task to set the enabled state of the device associated with this |
422 | * DeviceListener to aEnabled and notifies the associated window listener that |
423 | * a track's state has changed. |
424 | * |
425 | * Turning the hardware off while the device is disabled is supported for: |
426 | * - Camera (enabled by default, controlled by pref |
427 | * "media.getusermedia.camera.off_while_disabled.enabled") |
428 | * - Microphone (disabled by default, controlled by pref |
429 | * "media.getusermedia.microphone.off_while_disabled.enabled") |
430 | * Screen-, app-, or windowsharing is not supported at this time. |
431 | * |
432 | * The behavior is also different between disabling and enabling a device. |
433 | * While enabling is immediate, disabling only happens after a delay. |
434 | * This is now defaulting to 3 seconds but can be overriden by prefs: |
435 | * - "media.getusermedia.camera.off_while_disabled.delay_ms" and |
436 | * - "media.getusermedia.microphone.off_while_disabled.delay_ms". |
437 | * |
438 | * The delay is in place to prevent misuse by malicious sites. If a track is |
439 | * re-enabled before the delay has passed, the device will not be touched |
440 | * until another disable followed by the full delay happens. |
441 | */ |
442 | void SetDeviceEnabled(bool aEnabled); |
443 | |
444 | /** |
445 | * Posts a task to set the muted state of the device associated with this |
446 | * DeviceListener to aMuted and notifies the associated window listener that a |
447 | * track's state has changed. |
448 | * |
449 | * Turning the hardware off while the device is muted is supported for: |
450 | * - Camera (enabled by default, controlled by pref |
451 | * "media.getusermedia.camera.off_while_disabled.enabled") |
452 | * - Microphone (disabled by default, controlled by pref |
453 | * "media.getusermedia.microphone.off_while_disabled.enabled") |
454 | * Screen-, app-, or windowsharing is not supported at this time. |
455 | */ |
456 | void SetDeviceMuted(bool aMuted); |
457 | |
458 | /** |
459 | * Mutes or unmutes the associated video device if it is a camera. |
460 | */ |
461 | void MuteOrUnmuteCamera(bool aMute); |
462 | void MuteOrUnmuteMicrophone(bool aMute); |
463 | |
464 | LocalMediaDevice* GetDevice() const { |
465 | return mDeviceState ? mDeviceState->mDevice.get() : nullptr; |
466 | } |
467 | |
468 | bool Activated() const { return static_cast<bool>(mDeviceState); } |
469 | |
470 | bool Stopped() const { return mStopped; } |
471 | |
472 | bool CapturingVideo() const; |
473 | |
474 | bool CapturingAudio() const; |
475 | |
476 | CaptureState CapturingSource(MediaSourceEnum aSource) const; |
477 | |
478 | RefPtr<DeviceListenerPromise> ApplyConstraints( |
479 | const MediaTrackConstraints& aConstraints, CallerType aCallerType); |
480 | |
481 | PrincipalHandle GetPrincipalHandle() const; |
482 | |
483 | size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { |
484 | size_t amount = aMallocSizeOf(this); |
485 | // Assume mPrincipalHandle refers to a principal owned elsewhere. |
486 | // DeviceState does not have support for memory accounting. |
487 | return amount; |
488 | } |
489 | |
490 | private: |
491 | virtual ~DeviceListener() { |
492 | MOZ_ASSERT(mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mStopped", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 492); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ")" ); do { *((volatile int*)__null) = 492; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
493 | MOZ_ASSERT(!mWindowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mWindowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mWindowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mWindowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 493); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mWindowListener" ")"); do { *((volatile int*)__null) = 493; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
494 | } |
495 | |
496 | using DeviceOperationPromise = |
497 | MozPromise<nsresult, bool, /* IsExclusive = */ true>; |
498 | |
499 | /** |
500 | * Posts a task to start or stop the device associated with aTrack, based on |
501 | * a passed-in boolean. Private method used by SetDeviceEnabled and |
502 | * SetDeviceMuted. |
503 | */ |
504 | RefPtr<DeviceOperationPromise> UpdateDevice(bool aOn); |
505 | |
506 | // true after this listener has had all devices stopped. MainThread only. |
507 | bool mStopped; |
508 | |
509 | // never ever indirect off this; just for assertions |
510 | PRThread* mMainThreadCheck; |
511 | |
512 | // Set in Register() on main thread, then read from any thread. |
513 | PrincipalHandle mPrincipalHandle; |
514 | |
515 | // Weak pointer to the window listener that owns us. MainThread only. |
516 | GetUserMediaWindowListener* mWindowListener; |
517 | |
518 | // Accessed from MediaTrackGraph thread, MediaManager thread, and MainThread |
519 | // No locking needed as it's set on Activate() and never assigned to again. |
520 | UniquePtr<DeviceState> mDeviceState; |
521 | |
522 | MediaEventListener mCaptureEndedListener; |
523 | }; |
524 | |
525 | /** |
526 | * This class represents a WindowID and handles all MediaTrackListeners |
527 | * (here subclassed as DeviceListeners) used to feed GetUserMedia tracks. |
528 | * It proxies feedback from them into messages for browser chrome. |
529 | * The DeviceListeners are used to Start() and Stop() the underlying |
530 | * MediaEngineSource when MediaStreams are assigned and deassigned in content. |
531 | */ |
532 | class GetUserMediaWindowListener { |
533 | friend MediaManager; |
534 | |
535 | public: |
536 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GetUserMediaWindowListener)public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<GetUserMediaWindowListener>, "Reference-counted class " "GetUserMediaWindowListener" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 536; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("GetUserMediaWindowListener"), (uint32_t)(sizeof (*this))); return (nsrefcnt)count; } MozExternalRefCountType Release (void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 536 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("GetUserMediaWindowListener")); if (count == 0) { delete (this); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
537 | |
538 | // Create in an inactive state |
539 | GetUserMediaWindowListener(uint64_t aWindowID, |
540 | const PrincipalHandle& aPrincipalHandle) |
541 | : mWindowID(aWindowID), |
542 | mPrincipalHandle(aPrincipalHandle), |
543 | mChromeNotificationTaskPosted(false) {} |
544 | |
545 | /** |
546 | * Registers an inactive gUM device listener for this WindowListener. |
547 | */ |
548 | void Register(RefPtr<DeviceListener> aListener) { |
549 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 549); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 549; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
550 | MOZ_ASSERT(aListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aListener", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 550); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aListener" ")" ); do { *((volatile int*)__null) = 550; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
551 | MOZ_ASSERT(!aListener->Activated())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aListener->Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aListener->Activated())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aListener->Activated()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 551); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aListener->Activated()" ")"); do { *((volatile int*)__null) = 551; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
552 | MOZ_ASSERT(!mInactiveListeners.Contains(aListener), "Already registered")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)" " (" "Already registered" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 552); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)" ") (" "Already registered" ")"); do { *((volatile int*)__null ) = 552; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
553 | MOZ_ASSERT(!mActiveListeners.Contains(aListener), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "Already activated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 553); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "Already activated" ")"); do { *((volatile int*)__null ) = 553; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
554 | |
555 | aListener->Register(this); |
556 | mInactiveListeners.AppendElement(std::move(aListener)); |
557 | } |
558 | |
559 | /** |
560 | * Activates an already registered and inactive gUM device listener for this |
561 | * WindowListener. |
562 | */ |
563 | void Activate(RefPtr<DeviceListener> aListener, |
564 | RefPtr<LocalMediaDevice> aDevice, |
565 | RefPtr<LocalTrackSource> aTrackSource) { |
566 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 566); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 566; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
567 | MOZ_ASSERT(aListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aListener", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 567); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aListener" ")" ); do { *((volatile int*)__null) = 567; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
568 | MOZ_ASSERT(!aListener->Activated())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aListener->Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aListener->Activated())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aListener->Activated()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aListener->Activated()" ")"); do { *((volatile int*)__null) = 568; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
569 | MOZ_ASSERT(mInactiveListeners.Contains(aListener),do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mInactiveListeners.Contains(aListener)" " (" "Must be registered to activate" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Contains(aListener)" ") (" "Must be registered to activate" ")"); do { *((volatile int*)__null) = 570; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
570 | "Must be registered to activate")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mInactiveListeners.Contains(aListener)" " (" "Must be registered to activate" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Contains(aListener)" ") (" "Must be registered to activate" ")"); do { *((volatile int*)__null) = 570; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
571 | MOZ_ASSERT(!mActiveListeners.Contains(aListener), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "Already activated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "Already activated" ")"); do { *((volatile int*)__null ) = 571; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
572 | |
573 | bool muted = false; |
574 | if (aDevice->Kind() == MediaDeviceKind::Videoinput) { |
575 | muted = mCamerasAreMuted; |
576 | } else if (aDevice->Kind() == MediaDeviceKind::Audioinput) { |
577 | muted = mMicrophonesAreMuted; |
578 | } else { |
579 | MOZ_CRASH("Unexpected device kind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected device kind" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 579); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected device kind" ")"); do { *((volatile int*)__null) = 579; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
580 | } |
581 | |
582 | mInactiveListeners.RemoveElement(aListener); |
583 | aListener->Activate(std::move(aDevice), std::move(aTrackSource), muted); |
584 | mActiveListeners.AppendElement(std::move(aListener)); |
585 | } |
586 | |
587 | /** |
588 | * Removes all DeviceListeners from this window listener. |
589 | * Removes this window listener from the list of active windows, so callers |
590 | * need to make sure to hold a strong reference. |
591 | */ |
592 | void RemoveAll() { |
593 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 593; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
594 | |
595 | for (auto& l : mInactiveListeners.Clone()) { |
596 | Remove(l); |
597 | } |
598 | for (auto& l : mActiveListeners.Clone()) { |
599 | Remove(l); |
600 | } |
601 | MOZ_ASSERT(mInactiveListeners.Length() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInactiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInactiveListeners.Length() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Length() == 0" ")"); do { *((volatile int*)__null) = 601; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
602 | MOZ_ASSERT(mActiveListeners.Length() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mActiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mActiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mActiveListeners.Length() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActiveListeners.Length() == 0" ")"); do { *((volatile int*)__null) = 602; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
603 | |
604 | MediaManager* mgr = MediaManager::GetIfExists(); |
605 | if (!mgr) { |
606 | MOZ_ASSERT(false, "MediaManager should stay until everything is removed")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MediaManager should stay until everything is removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MediaManager should stay until everything is removed" ")"); do { *((volatile int*)__null) = 606; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false); |
607 | return; |
608 | } |
609 | GetUserMediaWindowListener* windowListener = |
610 | mgr->GetWindowListener(mWindowID); |
611 | |
612 | if (!windowListener) { |
613 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
614 | auto* globalWindow = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID); |
615 | if (globalWindow) { |
616 | auto req = MakeRefPtr<GetUserMediaRequest>( |
617 | globalWindow, VoidString(), VoidString(), |
618 | UserActivation::IsHandlingUserInput()); |
619 | obs->NotifyWhenScriptSafe(req, "recording-device-stopped", nullptr); |
620 | } |
621 | return; |
622 | } |
623 | |
624 | MOZ_ASSERT(windowListener == this,do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowListener == this)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowListener == this))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener == this" " (" "There should only be one window listener per window ID" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener == this" ") (" "There should only be one window listener per window ID" ")"); do { *((volatile int*)__null) = 625; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
625 | "There should only be one window listener per window ID")do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowListener == this)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowListener == this))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener == this" " (" "There should only be one window listener per window ID" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener == this" ") (" "There should only be one window listener per window ID" ")"); do { *((volatile int*)__null) = 625; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
626 | |
627 | LOG("GUMWindowListener %p removing windowID %" PRIu64"l" "u", this, mWindowID); |
628 | mgr->RemoveWindowID(mWindowID); |
629 | } |
630 | |
631 | /** |
632 | * Removes a listener from our lists. Safe to call without holding a hard |
633 | * reference. That said, you'll still want to iterate on a copy of said lists, |
634 | * if you end up calling this method (or methods that may call this method) in |
635 | * the loop, to avoid inadvertently skipping members. |
636 | * |
637 | * For use only from GetUserMediaWindowListener and DeviceListener. |
638 | */ |
639 | bool Remove(RefPtr<DeviceListener> aListener) { |
640 | // We refcount aListener on entry since we're going to proxy-release it |
641 | // below to prevent the refcount going to zero on callers who might be |
642 | // inside the listener, but operating without a hard reference to self. |
643 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 643; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
644 | |
645 | if (!mInactiveListeners.RemoveElement(aListener) && |
646 | !mActiveListeners.RemoveElement(aListener)) { |
647 | return false; |
648 | } |
649 | MOZ_ASSERT(!mInactiveListeners.Contains(aListener),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 651; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
650 | "A DeviceListener should only be once in one of "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 651; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
651 | "mInactiveListeners and mActiveListeners")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 651; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
652 | MOZ_ASSERT(!mActiveListeners.Contains(aListener),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 654; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
653 | "A DeviceListener should only be once in one of "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 654; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
654 | "mInactiveListeners and mActiveListeners")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 654; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
655 | |
656 | LOG("GUMWindowListener %p stopping DeviceListener %p.", this, |
657 | aListener.get()); |
658 | aListener->Stop(); |
659 | |
660 | if (LocalMediaDevice* removedDevice = aListener->GetDevice()) { |
661 | bool revokePermission = true; |
662 | nsString removedRawId; |
663 | nsString removedSourceType; |
664 | removedDevice->GetRawId(removedRawId); |
665 | removedDevice->GetMediaSource(removedSourceType); |
666 | |
667 | for (const auto& l : mActiveListeners) { |
668 | if (LocalMediaDevice* device = l->GetDevice()) { |
669 | nsString rawId; |
670 | device->GetRawId(rawId); |
671 | if (removedRawId.Equals(rawId)) { |
672 | revokePermission = false; |
673 | break; |
674 | } |
675 | } |
676 | } |
677 | |
678 | if (revokePermission) { |
679 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
680 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID); |
681 | auto req = MakeRefPtr<GetUserMediaRequest>( |
682 | window, removedRawId, removedSourceType, |
683 | UserActivation::IsHandlingUserInput()); |
684 | obs->NotifyWhenScriptSafe(req, "recording-device-stopped", nullptr); |
685 | } |
686 | } |
687 | |
688 | if (mInactiveListeners.Length() == 0 && mActiveListeners.Length() == 0) { |
689 | LOG("GUMWindowListener %p Removed last DeviceListener. Cleaning up.", |
690 | this); |
691 | RemoveAll(); |
692 | } |
693 | |
694 | nsCOMPtr<nsIEventTarget> mainTarget = do_GetMainThread(); |
695 | // To allow being invoked by callers not holding a strong reference to self, |
696 | // hold the listener alive until the stack has unwound, by always |
697 | // dispatching a runnable (aAlwaysProxy = true) |
698 | NS_ProxyRelease(__func__, mainTarget, aListener.forget(), true); |
699 | return true; |
700 | } |
701 | |
702 | /** |
703 | * Stops all screen/window/audioCapture sharing, but not camera or microphone. |
704 | */ |
705 | void StopSharing(); |
706 | |
707 | void StopRawID(const nsString& removedDeviceID); |
708 | |
709 | void MuteOrUnmuteCameras(bool aMute); |
710 | void MuteOrUnmuteMicrophones(bool aMute); |
711 | |
712 | /** |
713 | * Called by one of our DeviceListeners when one of its tracks has changed so |
714 | * that chrome state is affected. |
715 | * Schedules an event for the next stable state to update chrome. |
716 | */ |
717 | void ChromeAffectingStateChanged(); |
718 | |
719 | /** |
720 | * Called in stable state to send a notification to update chrome. |
721 | */ |
722 | void NotifyChrome(); |
723 | |
724 | bool CapturingVideo() const { |
725 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 725; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
726 | for (auto& l : mActiveListeners) { |
727 | if (l->CapturingVideo()) { |
728 | return true; |
729 | } |
730 | } |
731 | return false; |
732 | } |
733 | |
734 | bool CapturingAudio() const { |
735 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 735); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 735; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
736 | for (auto& l : mActiveListeners) { |
737 | if (l->CapturingAudio()) { |
738 | return true; |
739 | } |
740 | } |
741 | return false; |
742 | } |
743 | |
744 | CaptureState CapturingSource(MediaSourceEnum aSource) const { |
745 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 745; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
746 | CaptureState result = CaptureState::Off; |
747 | for (auto& l : mActiveListeners) { |
748 | result = CombineCaptureState(result, l->CapturingSource(aSource)); |
749 | } |
750 | return result; |
751 | } |
752 | |
753 | RefPtr<LocalMediaDeviceSetRefCnt> GetDevices() { |
754 | RefPtr devices = new LocalMediaDeviceSetRefCnt(); |
755 | for (auto& l : mActiveListeners) { |
756 | devices->AppendElement(l->GetDevice()); |
757 | } |
758 | return devices; |
759 | } |
760 | |
761 | uint64_t WindowID() const { return mWindowID; } |
762 | |
763 | PrincipalHandle GetPrincipalHandle() const { return mPrincipalHandle; } |
764 | |
765 | size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { |
766 | size_t amount = aMallocSizeOf(this); |
767 | // Assume mPrincipalHandle refers to a principal owned elsewhere. |
768 | amount += mInactiveListeners.ShallowSizeOfExcludingThis(aMallocSizeOf); |
769 | for (const RefPtr<DeviceListener>& listener : mInactiveListeners) { |
770 | amount += listener->SizeOfIncludingThis(aMallocSizeOf); |
771 | } |
772 | amount += mActiveListeners.ShallowSizeOfExcludingThis(aMallocSizeOf); |
773 | for (const RefPtr<DeviceListener>& listener : mActiveListeners) { |
774 | amount += listener->SizeOfIncludingThis(aMallocSizeOf); |
775 | } |
776 | return amount; |
777 | } |
778 | |
779 | private: |
780 | ~GetUserMediaWindowListener() { |
781 | MOZ_ASSERT(mInactiveListeners.Length() == 0,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInactiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInactiveListeners.Length() == 0" " (" "Inactive listeners should already be removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Length() == 0" ") (" "Inactive listeners should already be removed" ")"); do { *((volatile int*)__null) = 782; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
782 | "Inactive listeners should already be removed")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInactiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInactiveListeners.Length() == 0" " (" "Inactive listeners should already be removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 782); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Length() == 0" ") (" "Inactive listeners should already be removed" ")"); do { *((volatile int*)__null) = 782; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
783 | MOZ_ASSERT(mActiveListeners.Length() == 0,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mActiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mActiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mActiveListeners.Length() == 0" " (" "Active listeners should already be removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActiveListeners.Length() == 0" ") (" "Active listeners should already be removed" ")"); do { *((volatile int*)__null) = 784; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
784 | "Active listeners should already be removed")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mActiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mActiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mActiveListeners.Length() == 0" " (" "Active listeners should already be removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActiveListeners.Length() == 0" ") (" "Active listeners should already be removed" ")"); do { *((volatile int*)__null) = 784; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
785 | } |
786 | |
787 | uint64_t mWindowID; |
788 | const PrincipalHandle mPrincipalHandle; |
789 | |
790 | // true if we have scheduled a task to notify chrome in the next stable state. |
791 | // The task will reset this to false. MainThread only. |
792 | bool mChromeNotificationTaskPosted; |
793 | |
794 | nsTArray<RefPtr<DeviceListener>> mInactiveListeners; |
795 | nsTArray<RefPtr<DeviceListener>> mActiveListeners; |
796 | |
797 | // Whether camera and microphone access in this window are currently |
798 | // User Agent (UA) muted. When true, new and cloned tracks must start |
799 | // out muted, to avoid JS circumventing UA mute. Per-camera and |
800 | // per-microphone UA muting is not supported. |
801 | bool mCamerasAreMuted = false; |
802 | bool mMicrophonesAreMuted = false; |
803 | }; |
804 | |
805 | class LocalTrackSource : public MediaStreamTrackSource { |
806 | public: |
807 | LocalTrackSource(nsIPrincipal* aPrincipal, const nsString& aLabel, |
808 | const RefPtr<DeviceListener>& aListener, |
809 | MediaSourceEnum aSource, MediaTrack* aTrack, |
810 | RefPtr<PeerIdentity> aPeerIdentity, |
811 | TrackingId aTrackingId = TrackingId()) |
812 | : MediaStreamTrackSource(aPrincipal, aLabel, std::move(aTrackingId)), |
813 | mSource(aSource), |
814 | mTrack(aTrack), |
815 | mPeerIdentity(std::move(aPeerIdentity)), |
816 | mListener(aListener.get()) {} |
817 | |
818 | MediaSourceEnum GetMediaSource() const override { return mSource; } |
819 | |
820 | const PeerIdentity* GetPeerIdentity() const override { return mPeerIdentity; } |
821 | |
822 | RefPtr<MediaStreamTrackSource::ApplyConstraintsPromise> ApplyConstraints( |
823 | const MediaTrackConstraints& aConstraints, |
824 | CallerType aCallerType) override { |
825 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 825; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
826 | if (sHasMainThreadShutdown || !mListener) { |
827 | // Track has been stopped, or we are in shutdown. In either case |
828 | // there's no observable outcome, so pretend we succeeded. |
829 | return MediaStreamTrackSource::ApplyConstraintsPromise::CreateAndResolve( |
830 | false, __func__); |
831 | } |
832 | return mListener->ApplyConstraints(aConstraints, aCallerType); |
833 | } |
834 | |
835 | void GetSettings(MediaTrackSettings& aOutSettings) override { |
836 | if (mListener) { |
837 | mListener->GetSettings(aOutSettings); |
838 | } |
839 | } |
840 | |
841 | void GetCapabilities(MediaTrackCapabilities& aOutCapabilities) override { |
842 | if (mListener) { |
843 | mListener->GetCapabilities(aOutCapabilities); |
844 | } |
845 | } |
846 | |
847 | void Stop() override { |
848 | if (mListener) { |
849 | mListener->Stop(); |
850 | mListener = nullptr; |
851 | } |
852 | if (!mTrack->IsDestroyed()) { |
853 | mTrack->Destroy(); |
854 | } |
855 | } |
856 | |
857 | void Disable() override { |
858 | if (mListener) { |
859 | mListener->SetDeviceEnabled(false); |
860 | } |
861 | } |
862 | |
863 | void Enable() override { |
864 | if (mListener) { |
865 | mListener->SetDeviceEnabled(true); |
866 | } |
867 | } |
868 | |
869 | void Mute() { |
870 | MutedChanged(true); |
871 | mTrack->SetDisabledTrackMode(DisabledTrackMode::SILENCE_BLACK); |
872 | } |
873 | |
874 | void Unmute() { |
875 | MutedChanged(false); |
876 | mTrack->SetDisabledTrackMode(DisabledTrackMode::ENABLED); |
877 | } |
878 | |
879 | const MediaSourceEnum mSource; |
880 | const RefPtr<MediaTrack> mTrack; |
881 | const RefPtr<const PeerIdentity> mPeerIdentity; |
882 | |
883 | protected: |
884 | ~LocalTrackSource() { |
885 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 885); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 885; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
886 | MOZ_ASSERT(mTrack->IsDestroyed())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mTrack->IsDestroyed())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mTrack->IsDestroyed()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mTrack->IsDestroyed()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTrack->IsDestroyed()" ")"); do { *((volatile int*)__null) = 886; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
887 | } |
888 | |
889 | // This is a weak pointer to avoid having the DeviceListener (which may |
890 | // have references to threads and threadpools) kept alive by DOM-objects |
891 | // that may have ref-cycles and thus are released very late during |
892 | // shutdown, even after xpcom-shutdown-threads. See bug 1351655 for what |
893 | // can happen. |
894 | WeakPtr<DeviceListener> mListener; |
895 | }; |
896 | |
897 | class AudioCaptureTrackSource : public LocalTrackSource { |
898 | public: |
899 | AudioCaptureTrackSource(nsIPrincipal* aPrincipal, nsPIDOMWindowInner* aWindow, |
900 | const nsString& aLabel, |
901 | AudioCaptureTrack* aAudioCaptureTrack, |
902 | RefPtr<PeerIdentity> aPeerIdentity) |
903 | : LocalTrackSource(aPrincipal, aLabel, nullptr, |
904 | MediaSourceEnum::AudioCapture, aAudioCaptureTrack, |
905 | std::move(aPeerIdentity)), |
906 | mWindow(aWindow), |
907 | mAudioCaptureTrack(aAudioCaptureTrack) { |
908 | mAudioCaptureTrack->Start(); |
909 | mAudioCaptureTrack->Graph()->RegisterCaptureTrackForWindow( |
910 | mWindow->WindowID(), mAudioCaptureTrack); |
911 | mWindow->SetAudioCapture(true); |
912 | } |
913 | |
914 | void Stop() override { |
915 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 915); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 915; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
916 | if (!mAudioCaptureTrack->IsDestroyed()) { |
917 | MOZ_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 917); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")" ); do { *((volatile int*)__null) = 917; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
918 | mWindow->SetAudioCapture(false); |
919 | mAudioCaptureTrack->Graph()->UnregisterCaptureTrackForWindow( |
920 | mWindow->WindowID()); |
921 | mWindow = nullptr; |
922 | } |
923 | // LocalTrackSource destroys the track. |
924 | LocalTrackSource::Stop(); |
925 | MOZ_ASSERT(mAudioCaptureTrack->IsDestroyed())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mAudioCaptureTrack->IsDestroyed())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mAudioCaptureTrack->IsDestroyed ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mAudioCaptureTrack->IsDestroyed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudioCaptureTrack->IsDestroyed()" ")"); do { *((volatile int*)__null) = 925; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
926 | } |
927 | |
928 | ProcessedMediaTrack* InputTrack() const { return mAudioCaptureTrack.get(); } |
929 | |
930 | protected: |
931 | ~AudioCaptureTrackSource() { |
932 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 932; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
933 | MOZ_ASSERT(mAudioCaptureTrack->IsDestroyed())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mAudioCaptureTrack->IsDestroyed())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mAudioCaptureTrack->IsDestroyed ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mAudioCaptureTrack->IsDestroyed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudioCaptureTrack->IsDestroyed()" ")"); do { *((volatile int*)__null) = 933; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
934 | } |
935 | |
936 | RefPtr<nsPIDOMWindowInner> mWindow; |
937 | const RefPtr<AudioCaptureTrack> mAudioCaptureTrack; |
938 | }; |
939 | |
940 | /** |
941 | * nsIMediaDevice implementation. |
942 | */ |
943 | NS_IMPL_ISUPPORTS(LocalMediaDevice, nsIMediaDevice)MozExternalRefCountType LocalMediaDevice::AddRef(void) { static_assert (!std::is_destructible_v<LocalMediaDevice>, "Reference-counted class " "LocalMediaDevice" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 943; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("LocalMediaDevice" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("LocalMediaDevice" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"LocalMediaDevice\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"LocalMediaDevice\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 943; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("LocalMediaDevice" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("LocalMediaDevice" ), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType LocalMediaDevice::Release(void) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 943 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("LocalMediaDevice" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("LocalMediaDevice" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"LocalMediaDevice\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"LocalMediaDevice\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 943; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("LocalMediaDevice" " not thread-safe"); const char* const nametmp = "LocalMediaDevice"; nsrefcnt count = -- mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count ; } nsresult LocalMediaDevice::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 943); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<LocalMediaDevice, nsIMediaDevice>, int32_t ( reinterpret_cast<char*>(static_cast<nsIMediaDevice *>((LocalMediaDevice*)0x1000)) - reinterpret_cast<char* >((LocalMediaDevice*)0x1000))}, {&mozilla::detail::kImplementedIID <LocalMediaDevice, nsISupports>, int32_t(reinterpret_cast <char*>(static_cast<nsISupports*>( static_cast< nsIMediaDevice*>((LocalMediaDevice*)0x1000))) - reinterpret_cast <char*>((LocalMediaDevice*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface" ); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID , aInstancePtr, table); return rv; } |
944 | |
945 | MediaDevice::MediaDevice(MediaEngine* aEngine, MediaSourceEnum aMediaSource, |
946 | const nsString& aRawName, const nsString& aRawID, |
947 | const nsString& aRawGroupID, IsScary aIsScary, |
948 | const OsPromptable canRequestOsLevelPrompt, |
949 | const IsPlaceholder aIsPlaceholder) |
950 | : mEngine(aEngine), |
951 | mAudioDeviceInfo(nullptr), |
952 | mMediaSource(aMediaSource), |
953 | mKind(MediaEngineSource::IsVideo(aMediaSource) |
954 | ? MediaDeviceKind::Videoinput |
955 | : MediaDeviceKind::Audioinput), |
956 | mScary(aIsScary == IsScary::Yes), |
957 | mCanRequestOsLevelPrompt(canRequestOsLevelPrompt == OsPromptable::Yes), |
958 | mIsFake(mEngine->IsFake()), |
959 | mIsPlaceholder(aIsPlaceholder == IsPlaceholder::Yes), |
960 | mType(NS_ConvertASCIItoUTF16(dom::GetEnumString(mKind))), |
961 | mRawID(aRawID), |
962 | mRawGroupID(aRawGroupID), |
963 | mRawName(aRawName) { |
964 | MOZ_ASSERT(mEngine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mEngine)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mEngine))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mEngine", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mEngine" ")" ); do { *((volatile int*)__null) = 964; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
965 | } |
966 | |
967 | MediaDevice::MediaDevice(MediaEngine* aEngine, |
968 | const RefPtr<AudioDeviceInfo>& aAudioDeviceInfo, |
969 | const nsString& aRawID) |
970 | : mEngine(aEngine), |
971 | mAudioDeviceInfo(aAudioDeviceInfo), |
972 | mMediaSource(mAudioDeviceInfo->Type() == AudioDeviceInfo::TYPE_INPUT |
973 | ? MediaSourceEnum::Microphone |
974 | : MediaSourceEnum::Other), |
975 | mKind(mMediaSource == MediaSourceEnum::Microphone |
976 | ? MediaDeviceKind::Audioinput |
977 | : MediaDeviceKind::Audiooutput), |
978 | mScary(false), |
979 | mCanRequestOsLevelPrompt(false), |
980 | mIsFake(false), |
981 | mIsPlaceholder(false), |
982 | mType(NS_ConvertASCIItoUTF16(dom::GetEnumString(mKind))), |
983 | mRawID(aRawID), |
984 | mRawGroupID(mAudioDeviceInfo->GroupID()), |
985 | mRawName(mAudioDeviceInfo->Name()) {} |
986 | |
987 | /* static */ |
988 | RefPtr<MediaDevice> MediaDevice::CopyWithNewRawGroupId( |
989 | const RefPtr<MediaDevice>& aOther, const nsString& aRawGroupID) { |
990 | MOZ_ASSERT(!aOther->mAudioDeviceInfo, "device not supported")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aOther->mAudioDeviceInfo)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aOther->mAudioDeviceInfo ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!aOther->mAudioDeviceInfo" " (" "device not supported" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOther->mAudioDeviceInfo" ") (" "device not supported" ")"); do { *((volatile int*)__null ) = 990; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
991 | return new MediaDevice(aOther->mEngine, aOther->mMediaSource, |
992 | aOther->mRawName, aOther->mRawID, aRawGroupID, |
993 | IsScary(aOther->mScary), |
994 | OsPromptable(aOther->mCanRequestOsLevelPrompt), |
995 | IsPlaceholder(aOther->mIsPlaceholder)); |
996 | } |
997 | |
998 | MediaDevice::~MediaDevice() = default; |
999 | |
1000 | LocalMediaDevice::LocalMediaDevice(RefPtr<const MediaDevice> aRawDevice, |
1001 | const nsString& aID, |
1002 | const nsString& aGroupID, |
1003 | const nsString& aName) |
1004 | : mRawDevice(std::move(aRawDevice)), |
1005 | mName(aName), |
1006 | mID(aID), |
1007 | mGroupID(aGroupID) { |
1008 | MOZ_ASSERT(mRawDevice)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mRawDevice)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mRawDevice))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mRawDevice", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawDevice" ")"); do { *((volatile int*)__null) = 1008; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1009 | } |
1010 | |
1011 | /** |
1012 | * Helper functions that implement the constraints algorithm from |
1013 | * http://dev.w3.org/2011/webrtc/editor/getusermedia.html#methods-5 |
1014 | */ |
1015 | |
1016 | /* static */ |
1017 | bool LocalMediaDevice::StringsContain( |
1018 | const OwningStringOrStringSequence& aStrings, nsString aN) { |
1019 | return aStrings.IsString() ? aStrings.GetAsString() == aN |
1020 | : aStrings.GetAsStringSequence().Contains(aN); |
1021 | } |
1022 | |
1023 | /* static */ |
1024 | uint32_t LocalMediaDevice::FitnessDistance( |
1025 | nsString aN, const ConstrainDOMStringParameters& aParams) { |
1026 | if (aParams.mExact.WasPassed() && |
1027 | !StringsContain(aParams.mExact.Value(), aN)) { |
1028 | return UINT32_MAX(4294967295U); |
1029 | } |
1030 | if (aParams.mIdeal.WasPassed() && |
1031 | !StringsContain(aParams.mIdeal.Value(), aN)) { |
1032 | return 1; |
1033 | } |
1034 | return 0; |
1035 | } |
1036 | |
1037 | // Binding code doesn't templatize well... |
1038 | |
1039 | /* static */ |
1040 | uint32_t LocalMediaDevice::FitnessDistance( |
1041 | nsString aN, |
1042 | const OwningStringOrStringSequenceOrConstrainDOMStringParameters& |
1043 | aConstraint) { |
1044 | if (aConstraint.IsString()) { |
1045 | ConstrainDOMStringParameters params; |
1046 | params.mIdeal.Construct(); |
1047 | params.mIdeal.Value().SetAsString() = aConstraint.GetAsString(); |
1048 | return FitnessDistance(aN, params); |
1049 | } else if (aConstraint.IsStringSequence()) { |
1050 | ConstrainDOMStringParameters params; |
1051 | params.mIdeal.Construct(); |
1052 | params.mIdeal.Value().SetAsStringSequence() = |
1053 | aConstraint.GetAsStringSequence(); |
1054 | return FitnessDistance(aN, params); |
1055 | } else { |
1056 | return FitnessDistance(aN, aConstraint.GetAsConstrainDOMStringParameters()); |
1057 | } |
1058 | } |
1059 | |
1060 | uint32_t LocalMediaDevice::GetBestFitnessDistance( |
1061 | const nsTArray<const NormalizedConstraintSet*>& aConstraintSets, |
1062 | CallerType aCallerType) { |
1063 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1063); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1063; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1064 | MOZ_ASSERT(GetMediaSource() != MediaSourceEnum::Other)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetMediaSource() != MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(GetMediaSource() != MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetMediaSource() != MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetMediaSource() != MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 1064; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1065 | |
1066 | bool isChrome = aCallerType == CallerType::System; |
1067 | const nsString& id = isChrome ? RawID() : mID; |
1068 | auto type = GetMediaSource(); |
1069 | uint64_t distance = 0; |
1070 | if (!aConstraintSets.IsEmpty()) { |
1071 | if (isChrome /* For the screen/window sharing preview */ || |
1072 | type == MediaSourceEnum::Camera || |
1073 | type == MediaSourceEnum::Microphone) { |
1074 | distance += uint64_t(MediaConstraintsHelper::FitnessDistance( |
1075 | Some(id), aConstraintSets[0]->mDeviceId)) + |
1076 | uint64_t(MediaConstraintsHelper::FitnessDistance( |
1077 | Some(mGroupID), aConstraintSets[0]->mGroupId)); |
1078 | } |
1079 | } |
1080 | if (distance < UINT32_MAX(4294967295U)) { |
1081 | // Forward request to underlying object to interrogate per-mode |
1082 | // capabilities. |
1083 | distance += Source()->GetBestFitnessDistance(aConstraintSets); |
1084 | } |
1085 | return std::min<uint64_t>(distance, UINT32_MAX(4294967295U)); |
1086 | } |
1087 | |
1088 | NS_IMETHODIMPnsresult |
1089 | LocalMediaDevice::GetRawName(nsAString& aName) { |
1090 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1090; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1091 | aName.Assign(mRawDevice->mRawName); |
1092 | return NS_OK; |
1093 | } |
1094 | |
1095 | NS_IMETHODIMPnsresult |
1096 | LocalMediaDevice::GetType(nsAString& aType) { |
1097 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1097); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1097; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1098 | aType.Assign(mRawDevice->mType); |
1099 | return NS_OK; |
1100 | } |
1101 | |
1102 | NS_IMETHODIMPnsresult |
1103 | LocalMediaDevice::GetRawId(nsAString& aID) { |
1104 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1104); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1104; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1105 | aID.Assign(RawID()); |
1106 | return NS_OK; |
1107 | } |
1108 | |
1109 | NS_IMETHODIMPnsresult |
1110 | LocalMediaDevice::GetId(nsAString& aID) { |
1111 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1111); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1111; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1112 | aID.Assign(mID); |
1113 | return NS_OK; |
1114 | } |
1115 | |
1116 | NS_IMETHODIMPnsresult |
1117 | LocalMediaDevice::GetScary(bool* aScary) { |
1118 | *aScary = mRawDevice->mScary; |
1119 | return NS_OK; |
1120 | } |
1121 | |
1122 | NS_IMETHODIMPnsresult |
1123 | LocalMediaDevice::GetCanRequestOsLevelPrompt(bool* aCanRequestOsLevelPrompt) { |
1124 | *aCanRequestOsLevelPrompt = mRawDevice->mCanRequestOsLevelPrompt; |
1125 | return NS_OK; |
1126 | } |
1127 | |
1128 | void LocalMediaDevice::GetSettings(MediaTrackSettings& aOutSettings) { |
1129 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1129); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1129; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1130 | Source()->GetSettings(aOutSettings); |
1131 | } |
1132 | |
1133 | void LocalMediaDevice::GetCapabilities( |
1134 | MediaTrackCapabilities& aOutCapabilities) { |
1135 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1135); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1135; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1136 | Source()->GetCapabilities(aOutCapabilities); |
1137 | } |
1138 | |
1139 | MediaEngineSource* LocalMediaDevice::Source() { |
1140 | if (!mSource) { |
1141 | mSource = mRawDevice->mEngine->CreateSource(mRawDevice); |
1142 | } |
1143 | return mSource; |
1144 | } |
1145 | |
1146 | const TrackingId& LocalMediaDevice::GetTrackingId() const { |
1147 | return mSource->GetTrackingId(); |
1148 | } |
1149 | |
1150 | // Threadsafe since mKind and mSource are const. |
1151 | NS_IMETHODIMPnsresult |
1152 | LocalMediaDevice::GetMediaSource(nsAString& aMediaSource) { |
1153 | if (Kind() == MediaDeviceKind::Audiooutput) { |
1154 | aMediaSource.Truncate(); |
1155 | } else { |
1156 | aMediaSource.AssignASCII(dom::GetEnumString(GetMediaSource())); |
1157 | } |
1158 | return NS_OK; |
1159 | } |
1160 | |
1161 | nsresult LocalMediaDevice::Allocate(const MediaTrackConstraints& aConstraints, |
1162 | const MediaEnginePrefs& aPrefs, |
1163 | uint64_t aWindowID, |
1164 | const char** aOutBadConstraint) { |
1165 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1165; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1166 | |
1167 | // Mock failure for automated tests. |
1168 | if (IsFake() && aConstraints.mDeviceId.WasPassed() && |
1169 | aConstraints.mDeviceId.Value().IsString() && |
1170 | aConstraints.mDeviceId.Value().GetAsString().EqualsASCII("bad device")) { |
1171 | return NS_ERROR_FAILURE; |
1172 | } |
1173 | |
1174 | return Source()->Allocate(aConstraints, aPrefs, aWindowID, aOutBadConstraint); |
1175 | } |
1176 | |
1177 | void LocalMediaDevice::SetTrack(const RefPtr<MediaTrack>& aTrack, |
1178 | const PrincipalHandle& aPrincipalHandle) { |
1179 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1179; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1180 | Source()->SetTrack(aTrack, aPrincipalHandle); |
1181 | } |
1182 | |
1183 | nsresult LocalMediaDevice::Start() { |
1184 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1184; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1185 | MOZ_ASSERT(Source())do { static_assert( mozilla::detail::AssertionConditionType< decltype(Source())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(Source()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("Source()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1185); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Source()" ")" ); do { *((volatile int*)__null) = 1185; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1186 | return Source()->Start(); |
1187 | } |
1188 | |
1189 | nsresult LocalMediaDevice::Reconfigure( |
1190 | const MediaTrackConstraints& aConstraints, const MediaEnginePrefs& aPrefs, |
1191 | const char** aOutBadConstraint) { |
1192 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1192; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1193 | auto type = GetMediaSource(); |
1194 | if (type == MediaSourceEnum::Camera || type == MediaSourceEnum::Microphone) { |
1195 | NormalizedConstraints c(aConstraints); |
1196 | if (MediaConstraintsHelper::FitnessDistance(Some(mID), c.mDeviceId) == |
1197 | UINT32_MAX(4294967295U)) { |
1198 | *aOutBadConstraint = "deviceId"; |
1199 | return NS_ERROR_INVALID_ARG; |
1200 | } |
1201 | if (MediaConstraintsHelper::FitnessDistance(Some(mGroupID), c.mGroupId) == |
1202 | UINT32_MAX(4294967295U)) { |
1203 | *aOutBadConstraint = "groupId"; |
1204 | return NS_ERROR_INVALID_ARG; |
1205 | } |
1206 | } |
1207 | return Source()->Reconfigure(aConstraints, aPrefs, aOutBadConstraint); |
1208 | } |
1209 | |
1210 | nsresult LocalMediaDevice::FocusOnSelectedSource() { |
1211 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1211); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1211; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1212 | return Source()->FocusOnSelectedSource(); |
1213 | } |
1214 | |
1215 | nsresult LocalMediaDevice::Stop() { |
1216 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1216; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1217 | MOZ_ASSERT(mSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mSource))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mSource", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSource" ")" ); do { *((volatile int*)__null) = 1217; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1218 | return mSource->Stop(); |
1219 | } |
1220 | |
1221 | nsresult LocalMediaDevice::Deallocate() { |
1222 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1222; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1223 | MOZ_ASSERT(mSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mSource))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mSource", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSource" ")" ); do { *((volatile int*)__null) = 1223; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1224 | return mSource->Deallocate(); |
1225 | } |
1226 | |
1227 | MediaSourceEnum MediaDevice::GetMediaSource() const { return mMediaSource; } |
1228 | |
1229 | static const MediaTrackConstraints& GetInvariant( |
1230 | const OwningBooleanOrMediaTrackConstraints& aUnion) { |
1231 | static const MediaTrackConstraints empty; |
1232 | return aUnion.IsMediaTrackConstraints() ? aUnion.GetAsMediaTrackConstraints() |
1233 | : empty; |
1234 | } |
1235 | |
1236 | // Source getter returning full list |
1237 | |
1238 | static void GetMediaDevices(MediaEngine* aEngine, MediaSourceEnum aSrcType, |
1239 | MediaManager::MediaDeviceSet& aResult, |
1240 | const char* aMediaDeviceName = nullptr) { |
1241 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1241; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1242 | |
1243 | LOG("%s: aEngine=%p, aSrcType=%" PRIu8"u" ", aMediaDeviceName=%s", __func__, |
1244 | aEngine, static_cast<uint8_t>(aSrcType), |
1245 | aMediaDeviceName ? aMediaDeviceName : "null"); |
1246 | nsTArray<RefPtr<MediaDevice>> devices; |
1247 | aEngine->EnumerateDevices(aSrcType, MediaSinkEnum::Other, &devices); |
1248 | |
1249 | /* |
1250 | * We're allowing multiple tabs to access the same camera for parity |
1251 | * with Chrome. See bug 811757 for some of the issues surrounding |
1252 | * this decision. To disallow, we'd filter by IsAvailable() as we used |
1253 | * to. |
1254 | */ |
1255 | if (aMediaDeviceName && *aMediaDeviceName) { |
1256 | for (auto& device : devices) { |
1257 | if (device->mRawName.EqualsASCII(aMediaDeviceName)) { |
1258 | aResult.AppendElement(device); |
1259 | LOG("%s: found aMediaDeviceName=%s", __func__, aMediaDeviceName); |
1260 | break; |
1261 | } |
1262 | } |
1263 | } else { |
1264 | aResult = std::move(devices); |
1265 | if (MOZ_LOG_TEST(gMediaManagerLog, mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gMediaManagerLog , mozilla::LogLevel::Debug)), 0))) { |
1266 | for (auto& device : aResult) { |
1267 | LOG("%s: appending device=%s", __func__, |
1268 | NS_ConvertUTF16toUTF8(device->mRawName).get()); |
1269 | } |
1270 | } |
1271 | } |
1272 | } |
1273 | |
1274 | RefPtr<LocalDeviceSetPromise> MediaManager::SelectSettings( |
1275 | const MediaStreamConstraints& aConstraints, CallerType aCallerType, |
1276 | RefPtr<LocalMediaDeviceSetRefCnt> aDevices) { |
1277 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1277; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1278 | |
1279 | // Algorithm accesses device capabilities code and must run on media thread. |
1280 | // Modifies passed-in aDevices. |
1281 | |
1282 | return MediaManager::Dispatch<LocalDeviceSetPromise>( |
1283 | __func__, [aConstraints, devices = std::move(aDevices), |
1284 | aCallerType](MozPromiseHolder<LocalDeviceSetPromise>& holder) { |
1285 | auto& devicesRef = *devices; |
1286 | |
1287 | // Since the advanced part of the constraints algorithm needs to know |
1288 | // when a candidate set is overconstrained (zero members), we must split |
1289 | // up the list into videos and audios, and put it back together again at |
1290 | // the end. |
1291 | |
1292 | nsTArray<RefPtr<LocalMediaDevice>> videos; |
1293 | nsTArray<RefPtr<LocalMediaDevice>> audios; |
1294 | |
1295 | for (const auto& device : devicesRef) { |
1296 | MOZ_ASSERT(device->Kind() == MediaDeviceKind::Videoinput ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(device->Kind() == MediaDeviceKind::Videoinput || device ->Kind() == MediaDeviceKind::Audioinput)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(device->Kind() == MediaDeviceKind ::Videoinput || device->Kind() == MediaDeviceKind::Audioinput ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput" ")"); do { *((volatile int*)__null) = 1297; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1297 | device->Kind() == MediaDeviceKind::Audioinput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(device->Kind() == MediaDeviceKind::Videoinput || device ->Kind() == MediaDeviceKind::Audioinput)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(device->Kind() == MediaDeviceKind ::Videoinput || device->Kind() == MediaDeviceKind::Audioinput ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput" ")"); do { *((volatile int*)__null) = 1297; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1298 | if (device->Kind() == MediaDeviceKind::Videoinput) { |
1299 | videos.AppendElement(device); |
1300 | } else if (device->Kind() == MediaDeviceKind::Audioinput) { |
1301 | audios.AppendElement(device); |
1302 | } |
1303 | } |
1304 | devicesRef.Clear(); |
1305 | const char* badConstraint = nullptr; |
1306 | bool needVideo = IsOn(aConstraints.mVideo); |
1307 | bool needAudio = IsOn(aConstraints.mAudio); |
1308 | |
1309 | if (needVideo && videos.Length()) { |
1310 | badConstraint = MediaConstraintsHelper::SelectSettings( |
1311 | NormalizedConstraints(GetInvariant(aConstraints.mVideo)), videos, |
1312 | aCallerType); |
1313 | } |
1314 | if (!badConstraint && needAudio && audios.Length()) { |
1315 | badConstraint = MediaConstraintsHelper::SelectSettings( |
1316 | NormalizedConstraints(GetInvariant(aConstraints.mAudio)), audios, |
1317 | aCallerType); |
1318 | } |
1319 | if (badConstraint) { |
1320 | LOG("SelectSettings: bad constraint found! Calling error handler!"); |
1321 | nsString constraint; |
1322 | constraint.AssignASCII(badConstraint); |
1323 | holder.Reject( |
1324 | new MediaMgrError(MediaMgrError::Name::OverconstrainedError, "", |
1325 | constraint), |
1326 | __func__); |
1327 | return; |
1328 | } |
1329 | if (!needVideo == !videos.Length() && !needAudio == !audios.Length()) { |
1330 | for (auto& video : videos) { |
1331 | devicesRef.AppendElement(video); |
1332 | } |
1333 | for (auto& audio : audios) { |
1334 | devicesRef.AppendElement(audio); |
1335 | } |
1336 | } |
1337 | holder.Resolve(devices, __func__); |
1338 | }); |
1339 | } |
1340 | |
1341 | /** |
1342 | * Describes a requested task that handles response from the UI and sends |
1343 | * results back to the DOM. |
1344 | */ |
1345 | class GetUserMediaTask { |
1346 | public: |
1347 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GetUserMediaTask)public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<GetUserMediaTask>, "Reference-counted class " "GetUserMediaTask" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 1347; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("GetUserMediaTask"), (uint32_t)(sizeof(*this))); return (nsrefcnt)count; } MozExternalRefCountType Release(void ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1347); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 1347 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("GetUserMediaTask")); if (count == 0) { delete (this ); return 0; } return count; } using HasThreadSafeRefCnt = std ::true_type; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt ; public: |
1348 | GetUserMediaTask(uint64_t aWindowID, const ipc::PrincipalInfo& aPrincipalInfo, |
1349 | CallerType aCallerType) |
1350 | : mPrincipalInfo(aPrincipalInfo), |
1351 | mWindowID(aWindowID), |
1352 | mCallerType(aCallerType) {} |
1353 | |
1354 | virtual void Denied(MediaMgrError::Name aName, |
1355 | const nsCString& aMessage = ""_ns) = 0; |
1356 | |
1357 | virtual GetUserMediaStreamTask* AsGetUserMediaStreamTask() { return nullptr; } |
1358 | virtual SelectAudioOutputTask* AsSelectAudioOutputTask() { return nullptr; } |
1359 | |
1360 | uint64_t GetWindowID() const { return mWindowID; } |
1361 | enum CallerType CallerType() const { return mCallerType; } |
1362 | |
1363 | size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { |
1364 | size_t amount = aMallocSizeOf(this); |
1365 | // Assume mWindowListener is owned by MediaManager. |
1366 | // Assume mAudioDeviceListener and mVideoDeviceListener are owned by |
1367 | // mWindowListener. |
1368 | // Assume PrincipalInfo string buffers are shared. |
1369 | // Member types without support for accounting of pointees: |
1370 | // MozPromiseHolder, RefPtr<LocalMediaDevice>. |
1371 | // We don't have a good way to account for lambda captures for MozPromise |
1372 | // callbacks. |
1373 | return amount; |
1374 | } |
1375 | |
1376 | protected: |
1377 | virtual ~GetUserMediaTask() = default; |
1378 | |
1379 | // Call GetPrincipalKey again, if not private browing, this time with |
1380 | // persist = true, to promote deviceIds to persistent, in case they're not |
1381 | // already. Fire'n'forget. |
1382 | void PersistPrincipalKey() { |
1383 | if (IsPrincipalInfoPrivate(mPrincipalInfo)) { |
1384 | return; |
1385 | } |
1386 | media::GetPrincipalKey(mPrincipalInfo, true) |
1387 | ->Then( |
1388 | GetCurrentSerialEventTarget(), __func__, |
1389 | [](const media::PrincipalKeyPromise::ResolveOrRejectValue& aValue) { |
1390 | if (aValue.IsReject()) { |
1391 | LOG("Failed get Principal key. Persisting of deviceIds " |
1392 | "will be broken"); |
1393 | } |
1394 | }); |
1395 | } |
1396 | |
1397 | private: |
1398 | // Thread-safe (object) principal of Window with ID mWindowID |
1399 | const ipc::PrincipalInfo mPrincipalInfo; |
1400 | |
1401 | protected: |
1402 | // The ID of the not-necessarily-toplevel inner Window relevant global |
1403 | // object of the MediaDevices on which getUserMedia() was called |
1404 | const uint64_t mWindowID; |
1405 | // Whether the JS caller of getUserMedia() has system (subject) principal |
1406 | const enum CallerType mCallerType; |
1407 | }; |
1408 | |
1409 | /** |
1410 | * Describes a requested task that handles response from the UI to a |
1411 | * getUserMedia() request and sends results back to content. If the request |
1412 | * is allowed and device initialization succeeds, then the MozPromise is |
1413 | * resolved with a DOMMediaStream having a track or tracks for the approved |
1414 | * device or devices. |
1415 | */ |
1416 | class GetUserMediaStreamTask final : public GetUserMediaTask { |
1417 | public: |
1418 | GetUserMediaStreamTask( |
1419 | const MediaStreamConstraints& aConstraints, |
1420 | MozPromiseHolder<MediaManager::StreamPromise>&& aHolder, |
1421 | uint64_t aWindowID, RefPtr<GetUserMediaWindowListener> aWindowListener, |
1422 | RefPtr<DeviceListener> aAudioDeviceListener, |
1423 | RefPtr<DeviceListener> aVideoDeviceListener, |
1424 | const MediaEnginePrefs& aPrefs, const ipc::PrincipalInfo& aPrincipalInfo, |
1425 | enum CallerType aCallerType, bool aShouldFocusSource) |
1426 | : GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType), |
1427 | mConstraints(aConstraints), |
1428 | mHolder(std::move(aHolder)), |
1429 | mWindowListener(std::move(aWindowListener)), |
1430 | mAudioDeviceListener(std::move(aAudioDeviceListener)), |
1431 | mVideoDeviceListener(std::move(aVideoDeviceListener)), |
1432 | mPrefs(aPrefs), |
1433 | mShouldFocusSource(aShouldFocusSource), |
1434 | mManager(MediaManager::GetInstance()) {} |
1435 | |
1436 | void Allowed(RefPtr<LocalMediaDevice> aAudioDevice, |
1437 | RefPtr<LocalMediaDevice> aVideoDevice) { |
1438 | MOZ_ASSERT(aAudioDevice || aVideoDevice)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aAudioDevice || aVideoDevice)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aAudioDevice || aVideoDevice ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aAudioDevice || aVideoDevice", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioDevice || aVideoDevice" ")"); do { *((volatile int*)__null) = 1438; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1439 | mAudioDevice = std::move(aAudioDevice); |
1440 | mVideoDevice = std::move(aVideoDevice); |
1441 | // Reuse the same thread to save memory. |
1442 | MediaManager::Dispatch( |
1443 | NewRunnableMethod("GetUserMediaStreamTask::AllocateDevices", this, |
1444 | &GetUserMediaStreamTask::AllocateDevices)); |
1445 | } |
1446 | |
1447 | GetUserMediaStreamTask* AsGetUserMediaStreamTask() override { return this; } |
1448 | |
1449 | private: |
1450 | ~GetUserMediaStreamTask() override { |
1451 | if (!mHolder.IsEmpty()) { |
1452 | Fail(MediaMgrError::Name::NotAllowedError); |
1453 | } |
1454 | } |
1455 | |
1456 | void Fail(MediaMgrError::Name aName, const nsCString& aMessage = ""_ns, |
1457 | const nsString& aConstraint = u""_ns) { |
1458 | mHolder.Reject(MakeRefPtr<MediaMgrError>(aName, aMessage, aConstraint), |
1459 | __func__); |
1460 | // We add a disabled listener to the StreamListeners array until accepted |
1461 | // If this was the only active MediaStream, remove the window from the list. |
1462 | NS_DispatchToMainThread(NS_NewRunnableFunction( |
1463 | "DeviceListener::Stop", |
1464 | [audio = mAudioDeviceListener, video = mVideoDeviceListener] { |
1465 | if (audio) { |
1466 | audio->Stop(); |
1467 | } |
1468 | if (video) { |
1469 | video->Stop(); |
1470 | } |
1471 | })); |
1472 | } |
1473 | |
1474 | /** |
1475 | * Runs on a separate thread and is responsible for allocating devices. |
1476 | * |
1477 | * Do not run this on the main thread. |
1478 | */ |
1479 | void AllocateDevices() { |
1480 | MOZ_ASSERT(!NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1480; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1481 | LOG("GetUserMediaStreamTask::AllocateDevices()"); |
1482 | |
1483 | // Allocate a video or audio device and return a MediaStream via |
1484 | // PrepareDOMStream(). |
1485 | |
1486 | nsresult rv; |
1487 | const char* errorMsg = nullptr; |
1488 | const char* badConstraint = nullptr; |
1489 | |
1490 | if (mAudioDevice) { |
1491 | auto& constraints = GetInvariant(mConstraints.mAudio); |
1492 | rv = mAudioDevice->Allocate(constraints, mPrefs, mWindowID, |
1493 | &badConstraint); |
1494 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1495 | errorMsg = "Failed to allocate audiosource"; |
1496 | if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) { |
1497 | nsTArray<RefPtr<LocalMediaDevice>> devices; |
1498 | devices.AppendElement(mAudioDevice); |
1499 | badConstraint = MediaConstraintsHelper::SelectSettings( |
1500 | NormalizedConstraints(constraints), devices, mCallerType); |
1501 | } |
1502 | } |
1503 | } |
1504 | if (!errorMsg && mVideoDevice) { |
1505 | auto& constraints = GetInvariant(mConstraints.mVideo); |
1506 | rv = mVideoDevice->Allocate(constraints, mPrefs, mWindowID, |
1507 | &badConstraint); |
1508 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1509 | errorMsg = "Failed to allocate videosource"; |
1510 | if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) { |
1511 | nsTArray<RefPtr<LocalMediaDevice>> devices; |
1512 | devices.AppendElement(mVideoDevice); |
1513 | badConstraint = MediaConstraintsHelper::SelectSettings( |
1514 | NormalizedConstraints(constraints), devices, mCallerType); |
1515 | } |
1516 | if (mAudioDevice) { |
1517 | mAudioDevice->Deallocate(); |
1518 | } |
1519 | } else { |
1520 | mVideoTrackingId.emplace(mVideoDevice->GetTrackingId()); |
1521 | } |
1522 | } |
1523 | if (errorMsg) { |
1524 | LOG("%s %" PRIu32"u", errorMsg, static_cast<uint32_t>(rv)); |
1525 | if (badConstraint) { |
1526 | Fail(MediaMgrError::Name::OverconstrainedError, ""_ns, |
1527 | NS_ConvertUTF8toUTF16(badConstraint)); |
1528 | } else { |
1529 | Fail(MediaMgrError::Name::NotReadableError, nsCString(errorMsg)); |
1530 | } |
1531 | NS_DispatchToMainThread( |
1532 | NS_NewRunnableFunction("MediaManager::SendPendingGUMRequest", []() { |
1533 | if (MediaManager* manager = MediaManager::GetIfExists()) { |
1534 | manager->SendPendingGUMRequest(); |
1535 | } |
1536 | })); |
1537 | return; |
1538 | } |
1539 | NS_DispatchToMainThread( |
1540 | NewRunnableMethod("GetUserMediaStreamTask::PrepareDOMStream", this, |
1541 | &GetUserMediaStreamTask::PrepareDOMStream)); |
1542 | } |
1543 | |
1544 | public: |
1545 | void Denied(MediaMgrError::Name aName, const nsCString& aMessage) override { |
1546 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1546); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1546; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1547 | Fail(aName, aMessage); |
1548 | } |
1549 | |
1550 | const MediaStreamConstraints& GetConstraints() { return mConstraints; } |
1551 | |
1552 | void PrimeVoiceProcessing() { |
1553 | mPrimingStream = MakeAndAddRef<PrimingCubebVoiceInputStream>(); |
1554 | mPrimingStream->Init(); |
1555 | } |
1556 | |
1557 | private: |
1558 | void PrepareDOMStream(); |
1559 | |
1560 | class PrimingCubebVoiceInputStream { |
1561 | class Listener final : public CubebInputStream::Listener { |
1562 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Listener, override)public: MozExternalRefCountType AddRef(void) override { static_assert (!std::is_destructible_v<Listener>, "Reference-counted class " "Listener" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 1562; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("Listener"), (uint32_t)(sizeof(*this))); return ( nsrefcnt)count; } MozExternalRefCountType Release(void) override { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 1562 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("Listener")); if (count == 0) { delete (this); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type ; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public:; |
1563 | |
1564 | private: |
1565 | ~Listener() = default; |
1566 | |
1567 | long DataCallback(const void*, long) override { |
1568 | MOZ_CRASH("Unexpected data callback")do { do { } while (false); MOZ_ReportCrash("" "Unexpected data callback" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1568); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected data callback" ")"); do { *((volatile int*)__null) = 1568; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1569 | } |
1570 | void StateCallback(cubeb_state) override {} |
1571 | void DeviceChangedCallback() override {} |
1572 | }; |
1573 | |
1574 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_EVENT_TARGET(public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<PrimingCubebVoiceInputStream>, "Reference-counted class " "PrimingCubebVoiceInputStream" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 1575; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("PrimingCubebVoiceInputStream"), (uint32_t)(sizeof (*this))); return (nsrefcnt)count; } MozExternalRefCountType Release (void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 1575 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("PrimingCubebVoiceInputStream")); if (count == 0) { :: mozilla::detail::ProxyDeleteVoid( "ProxyDelete " "PrimingCubebVoiceInputStream" , mCubebThread.GetEventTarget(), this, [](void* self) { delete static_cast<PrimingCubebVoiceInputStream*>(self); }); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type ; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
1575 | PrimingCubebVoiceInputStream, mCubebThread.GetEventTarget())public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<PrimingCubebVoiceInputStream>, "Reference-counted class " "PrimingCubebVoiceInputStream" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 1575; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("PrimingCubebVoiceInputStream"), (uint32_t)(sizeof (*this))); return (nsrefcnt)count; } MozExternalRefCountType Release (void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 1575 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("PrimingCubebVoiceInputStream")); if (count == 0) { :: mozilla::detail::ProxyDeleteVoid( "ProxyDelete " "PrimingCubebVoiceInputStream" , mCubebThread.GetEventTarget(), this, [](void* self) { delete static_cast<PrimingCubebVoiceInputStream*>(self); }); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type ; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
1576 | |
1577 | public: |
1578 | void Init() { |
1579 | mCubebThread.GetEventTarget()->Dispatch( |
1580 | NS_NewRunnableFunction(__func__, [this, self = RefPtr(this)] { |
1581 | mCubebThread.AssertOnCurrentThread(); |
1582 | LOG("Priming voice processing with stream %p", this); |
1583 | TRACE("PrimingCubebVoiceInputStream::Init")AutoTracer trace(gAudioCallbackTraceLogger, "PrimingCubebVoiceInputStream::Init" );; |
1584 | const cubeb_devid default_device = nullptr; |
1585 | const uint32_t mono = 1; |
1586 | const uint32_t rate = CubebUtils::PreferredSampleRate(false); |
1587 | const bool isVoice = true; |
1588 | mCubebStream = |
1589 | CubebInputStream::Create(default_device, mono, rate, isVoice, |
1590 | MakeRefPtr<Listener>().get()); |
1591 | })); |
1592 | } |
1593 | |
1594 | private: |
1595 | ~PrimingCubebVoiceInputStream() { |
1596 | mCubebThread.AssertOnCurrentThread(); |
1597 | LOG("Releasing primed voice processing stream %p", this); |
1598 | mCubebStream = nullptr; |
1599 | } |
1600 | |
1601 | const EventTargetCapability<nsISerialEventTarget> mCubebThread = |
1602 | EventTargetCapability<nsISerialEventTarget>( |
1603 | TaskQueue::Create(CubebUtils::GetCubebOperationThread(), |
1604 | "PrimingCubebInputStream::mCubebThread") |
1605 | .get()); |
1606 | UniquePtr<CubebInputStream> mCubebStream MOZ_GUARDED_BY(mCubebThread)__attribute__((guarded_by(mCubebThread))); |
1607 | }; |
1608 | |
1609 | // Constraints derived from those passed to getUserMedia() but adjusted for |
1610 | // preferences, defaults, and security |
1611 | const MediaStreamConstraints mConstraints; |
1612 | |
1613 | MozPromiseHolder<MediaManager::StreamPromise> mHolder; |
1614 | // GetUserMediaWindowListener with which DeviceListeners are registered |
1615 | const RefPtr<GetUserMediaWindowListener> mWindowListener; |
1616 | const RefPtr<DeviceListener> mAudioDeviceListener; |
1617 | const RefPtr<DeviceListener> mVideoDeviceListener; |
1618 | // MediaDevices are set when selected and Allowed() by the UI. |
1619 | RefPtr<LocalMediaDevice> mAudioDevice; |
1620 | RefPtr<LocalMediaDevice> mVideoDevice; |
1621 | RefPtr<PrimingCubebVoiceInputStream> mPrimingStream; |
1622 | // Tracking id unique for a video frame source. Set when the corresponding |
1623 | // device has been allocated. |
1624 | Maybe<TrackingId> mVideoTrackingId; |
1625 | // Copy of MediaManager::mPrefs |
1626 | const MediaEnginePrefs mPrefs; |
1627 | // media.getusermedia.window.focus_source.enabled |
1628 | const bool mShouldFocusSource; |
1629 | // The MediaManager is referenced at construction so that it won't be |
1630 | // created after its ShutdownBlocker would run. |
1631 | const RefPtr<MediaManager> mManager; |
1632 | }; |
1633 | |
1634 | /** |
1635 | * Creates a MediaTrack, attaches a listener and resolves a MozPromise to |
1636 | * provide the stream to the DOM. |
1637 | * |
1638 | * All of this must be done on the main thread! |
1639 | */ |
1640 | void GetUserMediaStreamTask::PrepareDOMStream() { |
1641 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1641); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1641; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1642 | LOG("GetUserMediaStreamTask::PrepareDOMStream()"); |
1643 | nsGlobalWindowInner* window = |
1644 | nsGlobalWindowInner::GetInnerWindowWithId(mWindowID); |
1645 | |
1646 | // We're on main-thread, and the windowlist can only |
1647 | // be invalidated from the main-thread (see OnNavigation) |
1648 | if (!mManager->IsWindowListenerStillActive(mWindowListener)) { |
1649 | // This window is no longer live. mListener has already been removed. |
1650 | return; |
1651 | } |
1652 | |
1653 | MediaTrackGraph::GraphDriverType graphDriverType = |
1654 | mAudioDevice ? MediaTrackGraph::AUDIO_THREAD_DRIVER |
1655 | : MediaTrackGraph::SYSTEM_THREAD_DRIVER; |
1656 | MediaTrackGraph* mtg = MediaTrackGraph::GetInstance( |
1657 | graphDriverType, window, MediaTrackGraph::REQUEST_DEFAULT_SAMPLE_RATE, |
1658 | MediaTrackGraph::DEFAULT_OUTPUT_DEVICE); |
1659 | |
1660 | auto domStream = MakeRefPtr<DOMMediaStream>(window); |
1661 | RefPtr<LocalTrackSource> audioTrackSource; |
1662 | RefPtr<LocalTrackSource> videoTrackSource; |
1663 | nsCOMPtr<nsIPrincipal> principal; |
1664 | RefPtr<PeerIdentity> peerIdentity = nullptr; |
1665 | if (!mConstraints.mPeerIdentity.IsEmpty()) { |
1666 | peerIdentity = new PeerIdentity(mConstraints.mPeerIdentity); |
1667 | principal = NullPrincipal::CreateWithInheritedAttributes( |
1668 | window->GetExtantDoc()->NodePrincipal()); |
1669 | } else { |
1670 | principal = window->GetExtantDoc()->NodePrincipal(); |
1671 | } |
1672 | RefPtr<GenericNonExclusivePromise> firstFramePromise; |
1673 | if (mAudioDevice) { |
1674 | if (mAudioDevice->GetMediaSource() == MediaSourceEnum::AudioCapture) { |
1675 | // AudioCapture is a special case, here, in the sense that we're not |
1676 | // really using the audio source and the SourceMediaTrack, which acts |
1677 | // as placeholders. We re-route a number of tracks internally in the |
1678 | // MTG and mix them down instead. |
1679 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle " "MediaSourceEnum::AudioCapture. This must be fixed with UX " "before shipping.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1682) |
1680 | "MediaCaptureWindowState doesn't handle "NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle " "MediaSourceEnum::AudioCapture. This must be fixed with UX " "before shipping.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1682) |
1681 | "MediaSourceEnum::AudioCapture. This must be fixed with UX "NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle " "MediaSourceEnum::AudioCapture. This must be fixed with UX " "before shipping.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1682) |
1682 | "before shipping.")NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle " "MediaSourceEnum::AudioCapture. This must be fixed with UX " "before shipping.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1682); |
1683 | auto audioCaptureSource = MakeRefPtr<AudioCaptureTrackSource>( |
1684 | principal, window, u"Window audio capture"_ns, |
1685 | mtg->CreateAudioCaptureTrack(), peerIdentity); |
1686 | audioTrackSource = audioCaptureSource; |
1687 | RefPtr<MediaStreamTrack> track = new dom::AudioStreamTrack( |
1688 | window, audioCaptureSource->InputTrack(), audioCaptureSource); |
1689 | domStream->AddTrackInternal(track); |
1690 | } else { |
1691 | const nsString& audioDeviceName = mAudioDevice->mName; |
1692 | RefPtr<MediaTrack> track; |
1693 | #ifdef MOZ_WEBRTC1 |
1694 | if (mAudioDevice->IsFake()) { |
1695 | track = mtg->CreateSourceTrack(MediaSegment::AUDIO); |
1696 | } else { |
1697 | track = AudioProcessingTrack::Create(mtg); |
1698 | track->Suspend(); // Microphone source resumes in SetTrack |
1699 | } |
1700 | #else |
1701 | track = mtg->CreateSourceTrack(MediaSegment::AUDIO); |
1702 | #endif |
1703 | audioTrackSource = new LocalTrackSource( |
1704 | principal, audioDeviceName, mAudioDeviceListener, |
1705 | mAudioDevice->GetMediaSource(), track, peerIdentity); |
1706 | MOZ_ASSERT(MediaManager::IsOn(mConstraints.mAudio))do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsOn(mConstraints.mAudio))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(MediaManager::IsOn(mConstraints.mAudio)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaManager::IsOn(mConstraints.mAudio)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsOn(mConstraints.mAudio)" ")"); do { *((volatile int*)__null) = 1706; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1707 | RefPtr<MediaStreamTrack> domTrack = new dom::AudioStreamTrack( |
1708 | window, track, audioTrackSource, dom::MediaStreamTrackState::Live, |
1709 | false, GetInvariant(mConstraints.mAudio)); |
1710 | domStream->AddTrackInternal(domTrack); |
1711 | } |
1712 | } |
1713 | if (mVideoDevice) { |
1714 | const nsString& videoDeviceName = mVideoDevice->mName; |
1715 | RefPtr<MediaTrack> track = mtg->CreateSourceTrack(MediaSegment::VIDEO); |
1716 | videoTrackSource = new LocalTrackSource( |
1717 | principal, videoDeviceName, mVideoDeviceListener, |
1718 | mVideoDevice->GetMediaSource(), track, peerIdentity, *mVideoTrackingId); |
1719 | MOZ_ASSERT(MediaManager::IsOn(mConstraints.mVideo))do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsOn(mConstraints.mVideo))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(MediaManager::IsOn(mConstraints.mVideo)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaManager::IsOn(mConstraints.mVideo)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsOn(mConstraints.mVideo)" ")"); do { *((volatile int*)__null) = 1719; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1720 | RefPtr<MediaStreamTrack> domTrack = new dom::VideoStreamTrack( |
1721 | window, track, videoTrackSource, dom::MediaStreamTrackState::Live, |
1722 | false, GetInvariant(mConstraints.mVideo)); |
1723 | domStream->AddTrackInternal(domTrack); |
1724 | switch (mVideoDevice->GetMediaSource()) { |
1725 | case MediaSourceEnum::Browser: |
1726 | case MediaSourceEnum::Screen: |
1727 | case MediaSourceEnum::Window: |
1728 | // Wait for first frame for screen-sharing devices, to ensure |
1729 | // with and height settings are available immediately, to pass wpt. |
1730 | firstFramePromise = mVideoDevice->Source()->GetFirstFramePromise(); |
1731 | break; |
1732 | default: |
1733 | break; |
1734 | } |
1735 | } |
1736 | |
1737 | if (!domStream || (!audioTrackSource && !videoTrackSource) || |
1738 | sHasMainThreadShutdown) { |
1739 | LOG("Returning error for getUserMedia() - no stream"); |
1740 | |
1741 | mHolder.Reject( |
1742 | MakeRefPtr<MediaMgrError>( |
1743 | MediaMgrError::Name::AbortError, |
1744 | sHasMainThreadShutdown ? "In shutdown"_ns : "No stream."_ns), |
1745 | __func__); |
1746 | return; |
1747 | } |
1748 | |
1749 | // Activate our device listeners. We'll call Start() on the source when we |
1750 | // get a callback that the MediaStream has started consuming. The listener |
1751 | // is freed when the page is invalidated (on navigation or close). |
1752 | if (mAudioDeviceListener) { |
1753 | mWindowListener->Activate(mAudioDeviceListener, mAudioDevice, |
1754 | std::move(audioTrackSource)); |
1755 | } |
1756 | if (mVideoDeviceListener) { |
1757 | mWindowListener->Activate(mVideoDeviceListener, mVideoDevice, |
1758 | std::move(videoTrackSource)); |
1759 | } |
1760 | |
1761 | // Dispatch to the media thread to ask it to start the sources, because that |
1762 | // can take a while. |
1763 | typedef DeviceListener::DeviceListenerPromise PromiseType; |
1764 | AutoTArray<RefPtr<PromiseType>, 2> promises; |
1765 | if (mAudioDeviceListener) { |
1766 | promises.AppendElement(mAudioDeviceListener->InitializeAsync()); |
1767 | } |
1768 | if (mVideoDeviceListener) { |
1769 | promises.AppendElement(mVideoDeviceListener->InitializeAsync()); |
1770 | } |
1771 | PromiseType::All(GetMainThreadSerialEventTarget(), promises) |
1772 | ->Then( |
1773 | GetMainThreadSerialEventTarget(), __func__, |
1774 | [manager = mManager, windowListener = mWindowListener, |
1775 | firstFramePromise] { |
1776 | LOG("GetUserMediaStreamTask::PrepareDOMStream: starting success " |
1777 | "callback following InitializeAsync()"); |
1778 | // Initiating and starting devices succeeded. |
1779 | windowListener->ChromeAffectingStateChanged(); |
1780 | manager->SendPendingGUMRequest(); |
1781 | if (!firstFramePromise) { |
1782 | return DeviceListener::DeviceListenerPromise::CreateAndResolve( |
1783 | true, __func__); |
1784 | } |
1785 | RefPtr<DeviceListener::DeviceListenerPromise> resolvePromise = |
1786 | firstFramePromise->Then( |
1787 | GetMainThreadSerialEventTarget(), __func__, |
1788 | [] { |
1789 | return DeviceListener::DeviceListenerPromise:: |
1790 | CreateAndResolve(true, __func__); |
1791 | }, |
1792 | [](nsresult aError) { |
1793 | MOZ_ASSERT(NS_FAILED(aError))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aError)), 0))))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aError)), 0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(NS_FAILED_impl(aError)), 0)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aError)), 0)))" ")"); do { *((volatile int*)__null) = 1793; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1794 | if (aError == NS_ERROR_UNEXPECTED) { |
1795 | return DeviceListener::DeviceListenerPromise:: |
1796 | CreateAndReject( |
1797 | MakeRefPtr<MediaMgrError>( |
1798 | MediaMgrError::Name::NotAllowedError), |
1799 | __func__); |
1800 | } |
1801 | MOZ_ASSERT(aError == NS_ERROR_ABORT)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aError == NS_ERROR_ABORT)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aError == NS_ERROR_ABORT))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aError == NS_ERROR_ABORT" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aError == NS_ERROR_ABORT" ")"); do { *((volatile int*)__null) = 1801; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1802 | return DeviceListener::DeviceListenerPromise:: |
1803 | CreateAndReject(MakeRefPtr<MediaMgrError>( |
1804 | MediaMgrError::Name::AbortError, |
1805 | "In shutdown"), |
1806 | __func__); |
1807 | }); |
1808 | return resolvePromise; |
1809 | }, |
1810 | [audio = mAudioDeviceListener, |
1811 | video = mVideoDeviceListener](RefPtr<MediaMgrError>&& aError) { |
1812 | LOG("GetUserMediaStreamTask::PrepareDOMStream: starting failure " |
1813 | "callback following InitializeAsync()"); |
1814 | if (audio) { |
1815 | audio->Stop(); |
1816 | } |
1817 | if (video) { |
1818 | video->Stop(); |
1819 | } |
1820 | return DeviceListener::DeviceListenerPromise::CreateAndReject( |
1821 | aError, __func__); |
1822 | }) |
1823 | ->Then( |
1824 | GetMainThreadSerialEventTarget(), __func__, |
1825 | [holder = std::move(mHolder), domStream, callerType = mCallerType, |
1826 | shouldFocus = mShouldFocusSource, videoDevice = mVideoDevice]( |
1827 | const DeviceListener::DeviceListenerPromise::ResolveOrRejectValue& |
1828 | aValue) mutable { |
1829 | if (aValue.IsResolve()) { |
1830 | if (auto* mgr = MediaManager::GetIfExists(); |
1831 | mgr && !sHasMainThreadShutdown && videoDevice && |
1832 | callerType == CallerType::NonSystem && shouldFocus) { |
1833 | // Device was successfully started. Attempt to focus the |
1834 | // source. |
1835 | MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
1836 | mgr->mMediaThread->Dispatch(NS_NewRunnableFunction(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
1837 | "GetUserMediaStreamTask::FocusOnSelectedSource",do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
1838 | [videoDevice = std::move(videoDevice)] {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
1839 | nsresult rv = videoDevice->FocusOnSelectedSource();do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
1840 | if (NS_FAILED(rv)) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
1841 | LOG("FocusOnSelectedSource failed");do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
1842 | }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
1843 | })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1843; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); |
1844 | } |
1845 | |
1846 | holder.Resolve(domStream, __func__); |
1847 | } else { |
1848 | holder.Reject(aValue.RejectValue(), __func__); |
1849 | } |
1850 | }); |
1851 | |
1852 | PersistPrincipalKey(); |
1853 | } |
1854 | |
1855 | /** |
1856 | * Describes a requested task that handles response from the UI to a |
1857 | * selectAudioOutput() request and sends results back to content. If the |
1858 | * request is allowed, then the MozPromise is resolved with a MediaDevice |
1859 | * for the approved device. |
1860 | */ |
1861 | class SelectAudioOutputTask final : public GetUserMediaTask { |
1862 | public: |
1863 | SelectAudioOutputTask(MozPromiseHolder<LocalDevicePromise>&& aHolder, |
1864 | uint64_t aWindowID, enum CallerType aCallerType, |
1865 | const ipc::PrincipalInfo& aPrincipalInfo) |
1866 | : GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType), |
1867 | mHolder(std::move(aHolder)) {} |
1868 | |
1869 | void Allowed(RefPtr<LocalMediaDevice> aAudioOutput) { |
1870 | MOZ_ASSERT(aAudioOutput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aAudioOutput)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aAudioOutput))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aAudioOutput", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1870); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioOutput" ")"); do { *((volatile int*)__null) = 1870; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1871 | mHolder.Resolve(std::move(aAudioOutput), __func__); |
1872 | PersistPrincipalKey(); |
1873 | } |
1874 | |
1875 | void Denied(MediaMgrError::Name aName, const nsCString& aMessage) override { |
1876 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1876; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1877 | Fail(aName, aMessage); |
1878 | } |
1879 | |
1880 | SelectAudioOutputTask* AsSelectAudioOutputTask() override { return this; } |
1881 | |
1882 | private: |
1883 | ~SelectAudioOutputTask() override { |
1884 | if (!mHolder.IsEmpty()) { |
1885 | Fail(MediaMgrError::Name::NotAllowedError); |
1886 | } |
1887 | } |
1888 | |
1889 | void Fail(MediaMgrError::Name aName, const nsCString& aMessage = ""_ns) { |
1890 | mHolder.Reject(MakeRefPtr<MediaMgrError>(aName, aMessage), __func__); |
1891 | } |
1892 | |
1893 | private: |
1894 | MozPromiseHolder<LocalDevicePromise> mHolder; |
1895 | }; |
1896 | |
1897 | /* static */ |
1898 | void MediaManager::GuessVideoDeviceGroupIDs(MediaDeviceSet& aDevices, |
1899 | const MediaDeviceSet& aAudios) { |
1900 | // Run the logic in a lambda to avoid duplication. |
1901 | auto updateGroupIdIfNeeded = [&](RefPtr<MediaDevice>& aVideo, |
1902 | const MediaDeviceKind aKind) -> bool { |
1903 | MOZ_ASSERT(aVideo->mKind == MediaDeviceKind::Videoinput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aVideo->mKind == MediaDeviceKind::Videoinput)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aVideo->mKind == MediaDeviceKind::Videoinput))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("aVideo->mKind == MediaDeviceKind::Videoinput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVideo->mKind == MediaDeviceKind::Videoinput" ")"); do { *((volatile int*)__null) = 1903; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1904 | MOZ_ASSERT(aKind == MediaDeviceKind::Audioinput ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind ::Audiooutput)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1905); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput" ")"); do { *((volatile int*)__null) = 1905; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1905 | aKind == MediaDeviceKind::Audiooutput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind ::Audiooutput)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1905); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput" ")"); do { *((volatile int*)__null) = 1905; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1906 | // This will store the new group id if a match is found. |
1907 | nsString newVideoGroupID; |
1908 | // If the group id needs to be updated this will become true. It is |
1909 | // necessary when the new group id is an empty string. Without this extra |
1910 | // variable to signal the update, we would resort to test if |
1911 | // `newVideoGroupId` is empty. However, |
1912 | // that check does not work when the new group id is an empty string. |
1913 | bool updateGroupId = false; |
1914 | for (const RefPtr<MediaDevice>& dev : aAudios) { |
1915 | if (dev->mKind != aKind) { |
1916 | continue; |
1917 | } |
1918 | if (!FindInReadable(aVideo->mRawName, dev->mRawName)) { |
1919 | continue; |
1920 | } |
1921 | if (newVideoGroupID.IsEmpty()) { |
1922 | // This is only expected on first match. If that's the only match group |
1923 | // id will be updated to this one at the end of the loop. |
1924 | updateGroupId = true; |
1925 | newVideoGroupID = dev->mRawGroupID; |
1926 | } else { |
1927 | // More than one device found, it is impossible to know which group id |
1928 | // is the correct one. |
1929 | updateGroupId = false; |
1930 | newVideoGroupID = u""_ns; |
1931 | break; |
1932 | } |
1933 | } |
1934 | if (updateGroupId) { |
1935 | aVideo = MediaDevice::CopyWithNewRawGroupId(aVideo, newVideoGroupID); |
1936 | return true; |
1937 | } |
1938 | return false; |
1939 | }; |
1940 | |
1941 | for (RefPtr<MediaDevice>& video : aDevices) { |
1942 | if (video->mKind != MediaDeviceKind::Videoinput) { |
1943 | continue; |
1944 | } |
1945 | if (updateGroupIdIfNeeded(video, MediaDeviceKind::Audioinput)) { |
1946 | // GroupId has been updated, continue to the next video device |
1947 | continue; |
1948 | } |
1949 | // GroupId has not been updated, check among the outputs |
1950 | updateGroupIdIfNeeded(video, MediaDeviceKind::Audiooutput); |
1951 | } |
1952 | } |
1953 | |
1954 | namespace { |
1955 | |
1956 | // Class to hold the promise used to request device access and to resolve |
1957 | // even if |task| does not run, either because GeckoViewPermissionProcessChild |
1958 | // gets destroyed before ask-device-permission receives its |
1959 | // got-device-permission reply, or because the media thread is no longer |
1960 | // available. In either case, the process is shutting down so the result is |
1961 | // not important. Reject with a dummy error so the following Then-handler can |
1962 | // resolve with an empty set, so that callers do not need to handle rejection. |
1963 | class DeviceAccessRequestPromiseHolderWithFallback |
1964 | : public MozPromiseHolder<MozPromise< |
1965 | CamerasAccessStatus, mozilla::ipc::ResponseRejectReason, true>> { |
1966 | public: |
1967 | DeviceAccessRequestPromiseHolderWithFallback() = default; |
1968 | DeviceAccessRequestPromiseHolderWithFallback( |
1969 | DeviceAccessRequestPromiseHolderWithFallback&&) = default; |
1970 | ~DeviceAccessRequestPromiseHolderWithFallback() { |
1971 | if (!IsEmpty()) { |
1972 | Reject(ipc::ResponseRejectReason::ChannelClosed, __func__); |
1973 | } |
1974 | } |
1975 | }; |
1976 | |
1977 | } // anonymous namespace |
1978 | |
1979 | MediaManager::DeviceEnumerationParams::DeviceEnumerationParams( |
1980 | dom::MediaSourceEnum aInputType, DeviceType aType, |
1981 | nsAutoCString aForcedDeviceName) |
1982 | : mInputType(aInputType), |
1983 | mType(aType), |
1984 | mForcedDeviceName(std::move(aForcedDeviceName)) { |
1985 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1985; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1986 | MOZ_ASSERT(mInputType != dom::MediaSourceEnum::Other)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInputType != dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mInputType != dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mInputType != dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInputType != dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 1986; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1987 | MOZ_ASSERT_IF(!mForcedDeviceName.IsEmpty(), mType == DeviceType::Real)do { if (!mForcedDeviceName.IsEmpty()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(mType == DeviceType ::Real)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mType == DeviceType::Real))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mType == DeviceType::Real", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mType == DeviceType::Real" ")"); do { *((volatile int*)__null) = 1987; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1988 | } |
1989 | |
1990 | MediaManager::VideoDeviceEnumerationParams::VideoDeviceEnumerationParams( |
1991 | dom::MediaSourceEnum aInputType, DeviceType aType, |
1992 | nsAutoCString aForcedDeviceName, nsAutoCString aForcedMicrophoneName) |
1993 | : DeviceEnumerationParams(aInputType, aType, std::move(aForcedDeviceName)), |
1994 | mForcedMicrophoneName(std::move(aForcedMicrophoneName)) { |
1995 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1995); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1995; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1996 | MOZ_ASSERT_IF(!mForcedMicrophoneName.IsEmpty(),do { if (!mForcedMicrophoneName.IsEmpty()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(mInputType == dom::MediaSourceEnum::Camera)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInputType == dom::MediaSourceEnum ::Camera))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1997); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 1997; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1997 | mInputType == dom::MediaSourceEnum::Camera)do { if (!mForcedMicrophoneName.IsEmpty()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(mInputType == dom::MediaSourceEnum::Camera)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInputType == dom::MediaSourceEnum ::Camera))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1997); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 1997; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1998 | MOZ_ASSERT_IF(!mForcedMicrophoneName.IsEmpty(), mType == DeviceType::Real)do { if (!mForcedMicrophoneName.IsEmpty()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(mType == DeviceType::Real)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mType == DeviceType::Real))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("mType == DeviceType::Real" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1998); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mType == DeviceType::Real" ")"); do { *((volatile int*)__null) = 1998; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1999 | } |
2000 | |
2001 | MediaManager::EnumerationParams::EnumerationParams( |
2002 | EnumerationFlags aFlags, Maybe<VideoDeviceEnumerationParams> aVideo, |
2003 | Maybe<DeviceEnumerationParams> aAudio) |
2004 | : mFlags(aFlags), mVideo(std::move(aVideo)), mAudio(std::move(aAudio)) { |
2005 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2005; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2006 | MOZ_ASSERT_IF(mVideo, MediaEngineSource::IsVideo(mVideo->mInputType))do { if (mVideo) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(MediaEngineSource::IsVideo(mVideo->mInputType ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(MediaEngineSource::IsVideo(mVideo->mInputType)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaEngineSource::IsVideo(mVideo->mInputType)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaEngineSource::IsVideo(mVideo->mInputType)" ")"); do { *((volatile int*)__null) = 2006; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2007 | MOZ_ASSERT_IF(mVideo && !mVideo->mForcedDeviceName.IsEmpty(),do { if (mVideo && !mVideo->mForcedDeviceName.IsEmpty ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mVideo->mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 2008; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2008 | mVideo->mInputType == dom::MediaSourceEnum::Camera)do { if (mVideo && !mVideo->mForcedDeviceName.IsEmpty ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mVideo->mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 2008; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2009 | MOZ_ASSERT_IF(mVideo && mVideo->mType == DeviceType::Fake,do { if (mVideo && mVideo->mType == DeviceType::Fake ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mVideo->mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 2010; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2010 | mVideo->mInputType == dom::MediaSourceEnum::Camera)do { if (mVideo && mVideo->mType == DeviceType::Fake ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mVideo->mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 2010; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2011 | MOZ_ASSERT_IF(mAudio, MediaEngineSource::IsAudio(mAudio->mInputType))do { if (mAudio) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(MediaEngineSource::IsAudio(mAudio->mInputType ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(MediaEngineSource::IsAudio(mAudio->mInputType)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaEngineSource::IsAudio(mAudio->mInputType)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaEngineSource::IsAudio(mAudio->mInputType)" ")"); do { *((volatile int*)__null) = 2011; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2012 | MOZ_ASSERT_IF(mAudio && !mAudio->mForcedDeviceName.IsEmpty(),do { if (mAudio && !mAudio->mForcedDeviceName.IsEmpty ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone" ")"); do { *((volatile int*)__null) = 2013; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2013 | mAudio->mInputType == dom::MediaSourceEnum::Microphone)do { if (mAudio && !mAudio->mForcedDeviceName.IsEmpty ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone" ")"); do { *((volatile int*)__null) = 2013; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2014 | MOZ_ASSERT_IF(mAudio && mAudio->mType == DeviceType::Fake,do { if (mAudio && mAudio->mType == DeviceType::Fake ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone" ")"); do { *((volatile int*)__null) = 2015; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2015 | mAudio->mInputType == dom::MediaSourceEnum::Microphone)do { if (mAudio && mAudio->mType == DeviceType::Fake ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone" ")"); do { *((volatile int*)__null) = 2015; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2016 | } |
2017 | |
2018 | bool MediaManager::EnumerationParams::HasFakeCams() const { |
2019 | return mVideo |
2020 | .map([](const auto& aDev) { return aDev.mType == DeviceType::Fake; }) |
2021 | .valueOr(false); |
2022 | } |
2023 | |
2024 | bool MediaManager::EnumerationParams::HasFakeMics() const { |
2025 | return mAudio |
2026 | .map([](const auto& aDev) { return aDev.mType == DeviceType::Fake; }) |
2027 | .valueOr(false); |
2028 | } |
2029 | |
2030 | bool MediaManager::EnumerationParams::RealDeviceRequested() const { |
2031 | auto isReal = [](const auto& aDev) { return aDev.mType == DeviceType::Real; }; |
2032 | return mVideo.map(isReal).valueOr(false) || |
2033 | mAudio.map(isReal).valueOr(false) || |
2034 | mFlags.contains(EnumerationFlag::EnumerateAudioOutputs); |
2035 | } |
2036 | |
2037 | MediaSourceEnum MediaManager::EnumerationParams::VideoInputType() const { |
2038 | return mVideo.map([](const auto& aDev) { return aDev.mInputType; }) |
2039 | .valueOr(MediaSourceEnum::Other); |
2040 | } |
2041 | |
2042 | MediaSourceEnum MediaManager::EnumerationParams::AudioInputType() const { |
2043 | return mAudio.map([](const auto& aDev) { return aDev.mInputType; }) |
2044 | .valueOr(MediaSourceEnum::Other); |
2045 | } |
2046 | |
2047 | /* static */ MediaManager::EnumerationParams |
2048 | MediaManager::CreateEnumerationParams(dom::MediaSourceEnum aVideoInputType, |
2049 | dom::MediaSourceEnum aAudioInputType, |
2050 | EnumerationFlags aFlags) { |
2051 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2051); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2051; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2052 | MOZ_ASSERT_IF(!MediaEngineSource::IsVideo(aVideoInputType),do { if (!MediaEngineSource::IsVideo(aVideoInputType)) { do { static_assert( mozilla::detail::AssertionConditionType<decltype (aVideoInputType == dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aVideoInputType == dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aVideoInputType == dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVideoInputType == dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 2053; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2053 | aVideoInputType == dom::MediaSourceEnum::Other)do { if (!MediaEngineSource::IsVideo(aVideoInputType)) { do { static_assert( mozilla::detail::AssertionConditionType<decltype (aVideoInputType == dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aVideoInputType == dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aVideoInputType == dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVideoInputType == dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 2053; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2054 | MOZ_ASSERT_IF(!MediaEngineSource::IsAudio(aAudioInputType),do { if (!MediaEngineSource::IsAudio(aAudioInputType)) { do { static_assert( mozilla::detail::AssertionConditionType<decltype (aAudioInputType == dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aAudioInputType == dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aAudioInputType == dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioInputType == dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 2055; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2055 | aAudioInputType == dom::MediaSourceEnum::Other)do { if (!MediaEngineSource::IsAudio(aAudioInputType)) { do { static_assert( mozilla::detail::AssertionConditionType<decltype (aAudioInputType == dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aAudioInputType == dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aAudioInputType == dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioInputType == dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 2055; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2056 | const bool forceFakes = aFlags.contains(EnumerationFlag::ForceFakes); |
2057 | const bool fakeByPref = Preferences::GetBool("media.navigator.streams.fake"); |
2058 | Maybe<VideoDeviceEnumerationParams> videoParams; |
2059 | Maybe<DeviceEnumerationParams> audioParams; |
2060 | nsAutoCString audioDev; |
2061 | bool audioDevRead = false; |
2062 | constexpr const char* VIDEO_DEV_NAME = "media.video_loopback_dev"; |
2063 | constexpr const char* AUDIO_DEV_NAME = "media.audio_loopback_dev"; |
2064 | const auto ensureDev = [](const char* aPref, nsAutoCString* aLoopDev, |
2065 | bool* aPrefRead) { |
2066 | if (aPrefRead) { |
2067 | if (*aPrefRead) { |
2068 | return; |
2069 | } |
2070 | *aPrefRead = true; |
2071 | } |
2072 | |
2073 | if (NS_FAILED(Preferences::GetCString(aPref, *aLoopDev))((bool)(__builtin_expect(!!(NS_FAILED_impl(Preferences::GetCString (aPref, *aLoopDev))), 0)))) { |
2074 | // Ensure we fall back to an empty string if reading the pref failed. |
2075 | aLoopDev->SetIsVoid(true); |
2076 | } |
2077 | }; |
2078 | if (MediaEngineSource::IsVideo(aVideoInputType)) { |
2079 | nsAutoCString videoDev; |
2080 | DeviceType type = DeviceType::Real; |
2081 | if (aVideoInputType == MediaSourceEnum::Camera) { |
2082 | // Fake and loopback devices are supported for only Camera. |
2083 | if (forceFakes) { |
2084 | type = DeviceType::Fake; |
2085 | } else { |
2086 | ensureDev(VIDEO_DEV_NAME, &videoDev, nullptr); |
2087 | // Loopback prefs take precedence over fake prefs |
2088 | if (fakeByPref && videoDev.IsEmpty()) { |
2089 | type = DeviceType::Fake; |
2090 | } else { |
2091 | // For groupId correlation we need the audio device name. |
2092 | ensureDev(AUDIO_DEV_NAME, &audioDev, &audioDevRead); |
2093 | } |
2094 | } |
2095 | } |
2096 | videoParams = Some(VideoDeviceEnumerationParams(aVideoInputType, type, |
2097 | videoDev, audioDev)); |
2098 | } |
2099 | if (MediaEngineSource::IsAudio(aAudioInputType)) { |
2100 | nsAutoCString realAudioDev; |
2101 | DeviceType type = DeviceType::Real; |
2102 | if (aAudioInputType == MediaSourceEnum::Microphone) { |
2103 | // Fake and loopback devices are supported for only Microphone. |
2104 | if (forceFakes) { |
2105 | type = DeviceType::Fake; |
2106 | } else { |
2107 | ensureDev(AUDIO_DEV_NAME, &audioDev, &audioDevRead); |
2108 | // Loopback prefs take precedence over fake prefs |
2109 | if (fakeByPref && audioDev.IsEmpty()) { |
2110 | type = DeviceType::Fake; |
2111 | } else { |
2112 | realAudioDev = audioDev; |
2113 | } |
2114 | } |
2115 | } |
2116 | audioParams = |
2117 | Some(DeviceEnumerationParams(aAudioInputType, type, realAudioDev)); |
2118 | } |
2119 | return EnumerationParams(aFlags, videoParams, audioParams); |
2120 | } |
2121 | |
2122 | RefPtr<DeviceSetPromise> |
2123 | MediaManager::MaybeRequestPermissionAndEnumerateRawDevices( |
2124 | EnumerationParams aParams) { |
2125 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2125; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2126 | MOZ_ASSERT(aParams.mVideo.isSome() || aParams.mAudio.isSome() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)" ")"); do { *((volatile int*)__null) = 2127; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2127 | aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs))do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)" ")"); do { *((volatile int*)__null) = 2127; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2128 | |
2129 | LOG("%s: aVideoInputType=%" PRIu8"u" ", aAudioInputType=%" PRIu8"u", __func__, |
2130 | static_cast<uint8_t>(aParams.VideoInputType()), |
2131 | static_cast<uint8_t>(aParams.AudioInputType())); |
2132 | |
2133 | if (sHasMainThreadShutdown) { |
2134 | // The media thread is no longer available but the result will not be |
2135 | // observable. |
2136 | return DeviceSetPromise::CreateAndResolve( |
2137 | new MediaDeviceSetRefCnt(), |
2138 | "MaybeRequestPermissionAndEnumerateRawDevices: sync shutdown"); |
2139 | } |
2140 | |
2141 | const bool hasVideo = aParams.mVideo.isSome(); |
2142 | const bool hasAudio = aParams.mAudio.isSome(); |
2143 | const bool hasAudioOutput = |
2144 | aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs); |
2145 | const bool hasFakeCams = aParams.HasFakeCams(); |
2146 | const bool hasFakeMics = aParams.HasFakeMics(); |
2147 | // True if at least one of video input or audio input is a real device |
2148 | // or there is audio output. |
2149 | const bool realDeviceRequested = (!hasFakeCams && hasVideo) || |
2150 | (!hasFakeMics && hasAudio) || hasAudioOutput; |
2151 | |
2152 | using NativePromise = |
2153 | MozPromise<CamerasAccessStatus, mozilla::ipc::ResponseRejectReason, |
2154 | /* IsExclusive = */ true>; |
2155 | RefPtr<NativePromise> deviceAccessPromise; |
2156 | if (realDeviceRequested && |
2157 | aParams.mFlags.contains(EnumerationFlag::AllowPermissionRequest) && |
2158 | Preferences::GetBool("media.navigator.permission.device", false)) { |
2159 | // Need to ask permission to retrieve list of all devices; |
2160 | // notify frontend observer and wait for callback notification to post |
2161 | // task. |
2162 | const char16_t* const type = |
2163 | (aParams.VideoInputType() != MediaSourceEnum::Camera) ? u"audio" |
2164 | : (aParams.AudioInputType() != MediaSourceEnum::Microphone) ? u"video" |
2165 | : u"all"; |
2166 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
2167 | DeviceAccessRequestPromiseHolderWithFallback deviceAccessPromiseHolder; |
2168 | deviceAccessPromise = deviceAccessPromiseHolder.Ensure(__func__); |
2169 | RefPtr task = NS_NewRunnableFunction( |
2170 | __func__, [holder = std::move(deviceAccessPromiseHolder)]() mutable { |
2171 | holder.Resolve(CamerasAccessStatus::Granted, |
2172 | "getUserMedia:got-device-permission"); |
2173 | }); |
2174 | obs->NotifyObservers(static_cast<nsIRunnable*>(task), |
2175 | "getUserMedia:ask-device-permission", type); |
2176 | } else if (realDeviceRequested && hasVideo && |
2177 | aParams.VideoInputType() == MediaSourceEnum::Camera) { |
2178 | ipc::PBackgroundChild* backgroundChild = |
2179 | ipc::BackgroundChild::GetOrCreateForCurrentThread(); |
2180 | deviceAccessPromise = backgroundChild->SendRequestCameraAccess( |
2181 | aParams.mFlags.contains(EnumerationFlag::AllowPermissionRequest)); |
2182 | } |
2183 | |
2184 | if (!deviceAccessPromise) { |
2185 | // No device access request needed. We can proceed directly, but we still |
2186 | // need to update camera availability, because the camera engine is always |
2187 | // created together with the WebRTC backend, which is done because |
2188 | // devicechange events must work before prompting in cases where persistent |
2189 | // permission has already been given. Making a request to camera access not |
2190 | // allowing a permission request does exactly what we need in this case. |
2191 | ipc::PBackgroundChild* backgroundChild = |
2192 | ipc::BackgroundChild::GetOrCreateForCurrentThread(); |
2193 | deviceAccessPromise = backgroundChild->SendRequestCameraAccess(false); |
2194 | } |
2195 | |
2196 | return deviceAccessPromise->Then( |
2197 | GetCurrentSerialEventTarget(), __func__, |
2198 | [this, self = RefPtr(this), aParams = std::move(aParams)]( |
2199 | NativePromise::ResolveOrRejectValue&& aValue) mutable { |
2200 | if (sHasMainThreadShutdown) { |
2201 | return DeviceSetPromise::CreateAndResolve( |
2202 | new MediaDeviceSetRefCnt(), |
2203 | "MaybeRequestPermissionAndEnumerateRawDevices: async shutdown"); |
2204 | } |
2205 | |
2206 | if (aValue.IsReject()) { |
2207 | // IPC failure probably means we're in shutdown. Resolve with |
2208 | // an empty set, so that callers do not need to handle rejection. |
2209 | return DeviceSetPromise::CreateAndResolve( |
2210 | new MediaDeviceSetRefCnt(), |
2211 | "MaybeRequestPermissionAndEnumerateRawDevices: ipc failure"); |
2212 | } |
2213 | |
2214 | if (auto v = aValue.ResolveValue(); |
2215 | v == CamerasAccessStatus::Error || |
2216 | v == CamerasAccessStatus::Rejected) { |
2217 | LOG("Request to camera access %s", |
2218 | v == CamerasAccessStatus::Rejected ? "was rejected" : "failed"); |
2219 | if (v == CamerasAccessStatus::Error) { |
2220 | NS_WARNING("Failed to request camera access")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to request camera access" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2220); |
2221 | } |
2222 | return DeviceSetPromise::CreateAndReject( |
2223 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
2224 | "MaybeRequestPermissionAndEnumerateRawDevices: camera access " |
2225 | "rejected"); |
2226 | } |
2227 | |
2228 | if (aParams.VideoInputType() == MediaSourceEnum::Camera && |
2229 | aParams.mFlags.contains(EnumerationFlag::AllowPermissionRequest) && |
2230 | aValue.ResolveValue() == CamerasAccessStatus::Granted) { |
2231 | EnsureNoPlaceholdersInDeviceCache(); |
2232 | } |
2233 | |
2234 | // We have to nest this, unfortunately, since we have no guarantees that |
2235 | // mMediaThread is alive. If we'd reject due to shutdown above, and have |
2236 | // the below async operation in a Then handler on the media thread the |
2237 | // Then handler would fail to dispatch and trip an assert on |
2238 | // destruction, for instance. |
2239 | return InvokeAsync( |
2240 | mMediaThread, __func__, [aParams = std::move(aParams)]() mutable { |
2241 | return DeviceSetPromise::CreateAndResolve( |
2242 | EnumerateRawDevices(std::move(aParams)), |
2243 | "MaybeRequestPermissionAndEnumerateRawDevices: success"); |
2244 | }); |
2245 | }); |
2246 | } |
2247 | |
2248 | /** |
2249 | * EnumerateRawDevices - Enumerate a list of audio & video devices that |
2250 | * satisfy passed-in constraints. List contains raw id's. |
2251 | */ |
2252 | |
2253 | /* static */ RefPtr<MediaManager::MediaDeviceSetRefCnt> |
2254 | MediaManager::EnumerateRawDevices(EnumerationParams aParams) { |
2255 | MOZ_ASSERT(IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 2255; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2256 | // Only enumerate what's asked for, and only fake cams and mics. |
2257 | RefPtr<MediaEngine> fakeBackend, realBackend; |
2258 | if (aParams.HasFakeCams() || aParams.HasFakeMics()) { |
2259 | fakeBackend = new MediaEngineFake(); |
2260 | } |
2261 | if (aParams.RealDeviceRequested()) { |
2262 | MediaManager* manager = MediaManager::GetIfExists(); |
2263 | MOZ_RELEASE_ASSERT(manager, "Must exist while media thread is alive")do { static_assert( mozilla::detail::AssertionConditionType< decltype(manager)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(manager))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("manager" " (" "Must exist while media thread is alive" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2263); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "manager" ") (" "Must exist while media thread is alive" ")"); do { *( (volatile int*)__null) = 2263; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
2264 | realBackend = manager->GetBackend(); |
2265 | } |
2266 | |
2267 | RefPtr<MediaEngine> videoBackend; |
2268 | RefPtr<MediaEngine> audioBackend; |
2269 | Maybe<MediaDeviceSet> micsOfVideoBackend; |
2270 | Maybe<MediaDeviceSet> speakers; |
2271 | RefPtr devices = new MediaDeviceSetRefCnt(); |
2272 | |
2273 | // Enumerate microphones first, then cameras, then speakers, since |
2274 | // the enumerateDevices() algorithm expects them listed in that order. |
2275 | if (const auto& audio = aParams.mAudio; audio.isSome()) { |
2276 | audioBackend = aParams.HasFakeMics() ? fakeBackend : realBackend; |
2277 | MediaDeviceSet audios; |
2278 | LOG("EnumerateRawDevices: Getting audio sources with %s backend", |
2279 | audioBackend == fakeBackend ? "fake" : "real"); |
2280 | GetMediaDevices(audioBackend, audio->mInputType, audios, |
2281 | audio->mForcedDeviceName.get()); |
2282 | if (audio->mInputType == MediaSourceEnum::Microphone && |
2283 | audioBackend == videoBackend) { |
2284 | micsOfVideoBackend.emplace(); |
2285 | micsOfVideoBackend->AppendElements(audios); |
2286 | } |
2287 | devices->AppendElements(std::move(audios)); |
2288 | } |
2289 | if (const auto& video = aParams.mVideo; video.isSome()) { |
2290 | videoBackend = aParams.HasFakeCams() ? fakeBackend : realBackend; |
2291 | MediaDeviceSet videos; |
2292 | LOG("EnumerateRawDevices: Getting video sources with %s backend", |
2293 | videoBackend == fakeBackend ? "fake" : "real"); |
2294 | GetMediaDevices(videoBackend, video->mInputType, videos, |
2295 | video->mForcedDeviceName.get()); |
2296 | devices->AppendElements(std::move(videos)); |
2297 | } |
2298 | if (aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)) { |
2299 | MediaDeviceSet outputs; |
2300 | MOZ_ASSERT(realBackend)do { static_assert( mozilla::detail::AssertionConditionType< decltype(realBackend)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(realBackend))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("realBackend", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2300); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realBackend" ")"); do { *((volatile int*)__null) = 2300; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2301 | realBackend->EnumerateDevices(MediaSourceEnum::Other, |
2302 | MediaSinkEnum::Speaker, &outputs); |
2303 | speakers = Some(MediaDeviceSet()); |
2304 | speakers->AppendElements(outputs); |
2305 | devices->AppendElements(std::move(outputs)); |
2306 | } |
2307 | if (aParams.VideoInputType() == MediaSourceEnum::Camera) { |
2308 | MediaDeviceSet audios; |
2309 | LOG("EnumerateRawDevices: Getting audio sources with %s backend for " |
2310 | "groupId correlation", |
2311 | videoBackend == fakeBackend ? "fake" : "real"); |
2312 | // We need to correlate cameras with audio groupIds. We use the backend of |
2313 | // the camera to always do correlation on devices in the same scope. If we |
2314 | // don't do this, video-only getUserMedia will not apply groupId constraints |
2315 | // to the same set of groupIds as gets returned by enumerateDevices. |
2316 | if (micsOfVideoBackend.isSome()) { |
2317 | // Microphones from the same backend used for the cameras have |
2318 | // already been enumerated. Avoid doing it again. |
2319 | MOZ_ASSERT(aParams.mVideo->mForcedMicrophoneName ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParams.mVideo->mForcedMicrophoneName == aParams. mAudio->mForcedDeviceName)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2320); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName" ")"); do { *((volatile int*)__null) = 2320; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2320 | aParams.mAudio->mForcedDeviceName)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParams.mVideo->mForcedMicrophoneName == aParams. mAudio->mForcedDeviceName)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2320); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName" ")"); do { *((volatile int*)__null) = 2320; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2321 | audios.AppendElements(micsOfVideoBackend.extract()); |
2322 | } else { |
2323 | GetMediaDevices(videoBackend, MediaSourceEnum::Microphone, audios, |
2324 | aParams.mVideo->mForcedMicrophoneName.get()); |
2325 | } |
2326 | if (videoBackend == realBackend) { |
2327 | // When using the real backend for video, there could also be |
2328 | // speakers to correlate with. There are no fake speakers. |
2329 | if (speakers.isSome()) { |
2330 | // Speakers have already been enumerated. Avoid doing it again. |
2331 | audios.AppendElements(speakers.extract()); |
2332 | } else { |
2333 | realBackend->EnumerateDevices(MediaSourceEnum::Other, |
2334 | MediaSinkEnum::Speaker, &audios); |
2335 | } |
2336 | } |
2337 | GuessVideoDeviceGroupIDs(*devices, audios); |
2338 | } |
2339 | |
2340 | return devices; |
2341 | } |
2342 | |
2343 | RefPtr<ConstDeviceSetPromise> MediaManager::GetPhysicalDevices() { |
2344 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2344; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2345 | if (mPhysicalDevices) { |
2346 | return ConstDeviceSetPromise::CreateAndResolve(mPhysicalDevices, __func__); |
2347 | } |
2348 | if (mPendingDevicesPromises) { |
2349 | // Enumeration is already in progress. |
2350 | return mPendingDevicesPromises->AppendElement()->Ensure(__func__); |
2351 | } |
2352 | mPendingDevicesPromises = |
2353 | new Refcountable<nsTArray<MozPromiseHolder<ConstDeviceSetPromise>>>; |
2354 | MaybeRequestPermissionAndEnumerateRawDevices( |
2355 | CreateEnumerationParams(MediaSourceEnum::Camera, |
2356 | MediaSourceEnum::Microphone, |
2357 | EnumerationFlag::EnumerateAudioOutputs)) |
2358 | ->Then( |
2359 | GetCurrentSerialEventTarget(), __func__, |
2360 | [self = RefPtr(this), this, promises = mPendingDevicesPromises]( |
2361 | RefPtr<MediaDeviceSetRefCnt> aDevices) mutable { |
2362 | for (auto& promiseHolder : *promises) { |
2363 | promiseHolder.Resolve(aDevices, __func__); |
2364 | } |
2365 | // mPendingDevicesPromises may have changed if devices have changed. |
2366 | if (promises == mPendingDevicesPromises) { |
2367 | mPendingDevicesPromises = nullptr; |
2368 | mPhysicalDevices = std::move(aDevices); |
2369 | } |
2370 | }, |
2371 | [](RefPtr<MediaMgrError>&& reason) { |
2372 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "MaybeRequestPermissionAndEnumerateRawDevices does not reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2373); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "MaybeRequestPermissionAndEnumerateRawDevices does not reject" ")"); do { *((volatile int*)__null) = 2373; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2373 | "MaybeRequestPermissionAndEnumerateRawDevices does not reject")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "MaybeRequestPermissionAndEnumerateRawDevices does not reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2373); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "MaybeRequestPermissionAndEnumerateRawDevices does not reject" ")"); do { *((volatile int*)__null) = 2373; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2374 | }); |
2375 | |
2376 | return mPendingDevicesPromises->AppendElement()->Ensure(__func__); |
2377 | } |
2378 | |
2379 | MediaManager::MediaManager(already_AddRefed<TaskQueue> aMediaThread) |
2380 | : mMediaThread(aMediaThread), mBackend(nullptr) { |
2381 | mPrefs.mFreq = 1000; // 1KHz test tone |
2382 | mPrefs.mWidth = 0; // adaptive default |
2383 | mPrefs.mHeight = 0; // adaptive default |
2384 | mPrefs.mFPS = MediaEnginePrefs::DEFAULT_VIDEO_FPS; |
2385 | mPrefs.mUsePlatformProcessing = false; |
2386 | mPrefs.mAecOn = false; |
2387 | mPrefs.mUseAecMobile = false; |
2388 | mPrefs.mAgcOn = false; |
2389 | mPrefs.mHPFOn = false; |
2390 | mPrefs.mNoiseOn = false; |
2391 | mPrefs.mTransientOn = false; |
2392 | mPrefs.mAgc2Forced = false; |
2393 | mPrefs.mExpectDrift = -1; // auto |
2394 | #ifdef MOZ_WEBRTC1 |
2395 | mPrefs.mAgc = |
2396 | webrtc::AudioProcessing::Config::GainController1::Mode::kAdaptiveDigital; |
2397 | mPrefs.mNoise = |
2398 | webrtc::AudioProcessing::Config::NoiseSuppression::Level::kModerate; |
2399 | #else |
2400 | mPrefs.mAgc = 0; |
2401 | mPrefs.mNoise = 0; |
2402 | #endif |
2403 | mPrefs.mChannels = 0; // max channels default |
2404 | nsresult rv; |
2405 | nsCOMPtr<nsIPrefService> prefs = |
2406 | do_GetService("@mozilla.org/preferences-service;1", &rv); |
2407 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
2408 | nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs); |
2409 | if (branch) { |
2410 | GetPrefs(branch, nullptr); |
2411 | } |
2412 | } |
2413 | } |
2414 | |
2415 | NS_IMPL_ISUPPORTS(MediaManager, nsIMediaManagerService, nsIMemoryReporter,MozExternalRefCountType MediaManager::AddRef(void) { static_assert (!std::is_destructible_v<MediaManager>, "Reference-counted class " "MediaManager" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 2416; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 2416; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("MediaManager" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("MediaManager" ), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType MediaManager::Release(void) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(int32_t(mRefCnt) > 0) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 2416 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 2416; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("MediaManager" " not thread-safe"); const char * const nametmp = "MediaManager"; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult MediaManager::QueryInterface(const nsIID& aIID, void** aInstancePtr ) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(3 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<MediaManager, nsIMediaManagerService> , int32_t( reinterpret_cast<char*>(static_cast<nsIMediaManagerService *>((MediaManager*)0x1000)) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID <MediaManager, nsIMemoryReporter>, int32_t( reinterpret_cast <char*>(static_cast<nsIMemoryReporter*>((MediaManager *)0x1000)) - reinterpret_cast<char*>((MediaManager*)0x1000 ))}, {&mozilla::detail::kImplementedIID<MediaManager, nsIObserver >, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver *>((MediaManager*)0x1000)) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID <MediaManager, nsISupports>, int32_t(reinterpret_cast< char*>(static_cast<nsISupports*>( static_cast<nsIMediaManagerService *>((MediaManager*)0x1000))) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, { nullptr, 0 } } ; static_assert(std ::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
2416 | nsIObserver)MozExternalRefCountType MediaManager::AddRef(void) { static_assert (!std::is_destructible_v<MediaManager>, "Reference-counted class " "MediaManager" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 2416; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 2416; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("MediaManager" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("MediaManager" ), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType MediaManager::Release(void) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(int32_t(mRefCnt) > 0) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 2416 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 2416; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("MediaManager" " not thread-safe"); const char * const nametmp = "MediaManager"; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult MediaManager::QueryInterface(const nsIID& aIID, void** aInstancePtr ) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2416); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(3 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<MediaManager, nsIMediaManagerService> , int32_t( reinterpret_cast<char*>(static_cast<nsIMediaManagerService *>((MediaManager*)0x1000)) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID <MediaManager, nsIMemoryReporter>, int32_t( reinterpret_cast <char*>(static_cast<nsIMemoryReporter*>((MediaManager *)0x1000)) - reinterpret_cast<char*>((MediaManager*)0x1000 ))}, {&mozilla::detail::kImplementedIID<MediaManager, nsIObserver >, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver *>((MediaManager*)0x1000)) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID <MediaManager, nsISupports>, int32_t(reinterpret_cast< char*>(static_cast<nsISupports*>( static_cast<nsIMediaManagerService *>((MediaManager*)0x1000))) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, { nullptr, 0 } } ; static_assert(std ::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
2417 | |
2418 | /* static */ |
2419 | StaticRefPtr<MediaManager> MediaManager::sSingleton; |
2420 | |
2421 | #ifdef DEBUG1 |
2422 | /* static */ |
2423 | bool MediaManager::IsInMediaThread() { |
2424 | return sSingleton && sSingleton->mMediaThread->IsOnCurrentThread(); |
2425 | } |
2426 | #endif |
2427 | |
2428 | template <typename Function> |
2429 | static void ForeachObservedPref(const Function& aFunction) { |
2430 | aFunction("media.navigator.video.default_width"_ns); |
2431 | aFunction("media.navigator.video.default_height"_ns); |
2432 | aFunction("media.navigator.video.default_fps"_ns); |
2433 | aFunction("media.navigator.audio.fake_frequency"_ns); |
2434 | aFunction("media.audio_loopback_dev"_ns); |
2435 | aFunction("media.video_loopback_dev"_ns); |
2436 | aFunction("media.getusermedia.fake-camera-name"_ns); |
2437 | #ifdef MOZ_WEBRTC1 |
2438 | aFunction("media.getusermedia.audio.processing.aec.enabled"_ns); |
2439 | aFunction("media.getusermedia.audio.processing.aec"_ns); |
2440 | aFunction("media.getusermedia.audio.processing.agc.enabled"_ns); |
2441 | aFunction("media.getusermedia.audio.processing.agc"_ns); |
2442 | aFunction("media.getusermedia.audio.processing.hpf.enabled"_ns); |
2443 | aFunction("media.getusermedia.audio.processing.noise.enabled"_ns); |
2444 | aFunction("media.getusermedia.audio.processing.noise"_ns); |
2445 | aFunction("media.getusermedia.audio.max_channels"_ns); |
2446 | aFunction("media.navigator.streams.fake"_ns); |
2447 | #endif |
2448 | } |
2449 | |
2450 | // NOTE: never NS_DispatchAndSpinEventLoopUntilComplete to the MediaManager |
2451 | // thread from the MainThread, as we NS_DispatchAndSpinEventLoopUntilComplete to |
2452 | // MainThread from MediaManager thread. |
2453 | |
2454 | // Guaranteed never to return nullptr. |
2455 | /* static */ |
2456 | MediaManager* MediaManager::Get() { |
2457 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2457; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2458 | |
2459 | if (!sSingleton) { |
2460 | static int timesCreated = 0; |
2461 | timesCreated++; |
2462 | MOZ_RELEASE_ASSERT(timesCreated == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(timesCreated == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(timesCreated == 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("timesCreated == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2462); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "timesCreated == 1" ")"); do { *((volatile int*)__null) = 2462; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2463 | |
2464 | RefPtr<TaskQueue> mediaThread = TaskQueue::Create( |
2465 | GetMediaThreadPool(MediaThreadType::SUPERVISOR), "MediaManager"); |
2466 | LOG("New Media thread for gum"); |
2467 | |
2468 | sSingleton = new MediaManager(mediaThread.forget()); |
2469 | |
2470 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
2471 | if (obs) { |
2472 | obs->AddObserver(sSingleton, "last-pb-context-exited", false); |
2473 | obs->AddObserver(sSingleton, "getUserMedia:got-device-permission", false); |
2474 | obs->AddObserver(sSingleton, "getUserMedia:privileged:allow", false); |
2475 | obs->AddObserver(sSingleton, "getUserMedia:response:allow", false); |
2476 | obs->AddObserver(sSingleton, "getUserMedia:response:deny", false); |
2477 | obs->AddObserver(sSingleton, "getUserMedia:response:noOSPermission", |
2478 | false); |
2479 | obs->AddObserver(sSingleton, "getUserMedia:revoke", false); |
2480 | obs->AddObserver(sSingleton, "getUserMedia:muteVideo", false); |
2481 | obs->AddObserver(sSingleton, "getUserMedia:unmuteVideo", false); |
2482 | obs->AddObserver(sSingleton, "getUserMedia:muteAudio", false); |
2483 | obs->AddObserver(sSingleton, "getUserMedia:unmuteAudio", false); |
2484 | obs->AddObserver(sSingleton, "application-background", false); |
2485 | obs->AddObserver(sSingleton, "application-foreground", false); |
2486 | } |
2487 | // else MediaManager won't work properly and will leak (see bug 837874) |
2488 | nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1"); |
2489 | if (prefs) { |
2490 | ForeachObservedPref([&](const nsLiteralCString& aPrefName) { |
2491 | prefs->AddObserver(aPrefName, sSingleton, false); |
2492 | }); |
2493 | } |
2494 | RegisterStrongMemoryReporter(sSingleton); |
2495 | |
2496 | // Prepare async shutdown |
2497 | |
2498 | class Blocker : public media::ShutdownBlocker { |
2499 | public: |
2500 | Blocker() |
2501 | : media::ShutdownBlocker( |
2502 | u"Media shutdown: blocking on media thread"_ns) {} |
2503 | |
2504 | NS_IMETHODvirtual nsresult BlockShutdown(nsIAsyncShutdownClient*) override { |
2505 | MOZ_RELEASE_ASSERT(MediaManager::GetIfExists())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::GetIfExists())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::GetIfExists()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaManager::GetIfExists()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2505); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "MediaManager::GetIfExists()" ")"); do { *((volatile int*)__null) = 2505; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2506 | MediaManager::GetIfExists()->Shutdown(); |
2507 | return NS_OK; |
2508 | } |
2509 | }; |
2510 | |
2511 | sSingleton->mShutdownBlocker = new Blocker(); |
2512 | nsresult rv = media::MustGetShutdownBarrier()->AddBlocker( |
2513 | sSingleton->mShutdownBlocker, NS_LITERAL_STRING_FROM_CSTRING(__FILE__)static_cast<const nsLiteralString&>( nsLiteralString (u"" "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" )), |
2514 | __LINE__2514, u""_ns); |
2515 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2515); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2515; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2516 | } |
2517 | return sSingleton; |
2518 | } |
2519 | |
2520 | /* static */ |
2521 | MediaManager* MediaManager::GetIfExists() { |
2522 | MOZ_ASSERT(NS_IsMainThread() || IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread() || IsInMediaThread())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(NS_IsMainThread() || IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread() || IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || IsInMediaThread()" ")"); do { *((volatile int*)__null) = 2522; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2523 | return sSingleton; |
2524 | } |
2525 | |
2526 | /* static */ |
2527 | already_AddRefed<MediaManager> MediaManager::GetInstance() { |
2528 | // so we can have non-refcounted getters |
2529 | RefPtr<MediaManager> service = MediaManager::Get(); |
2530 | return service.forget(); |
2531 | } |
2532 | |
2533 | media::Parent<media::NonE10s>* MediaManager::GetNonE10sParent() { |
2534 | if (!mNonE10sParent) { |
2535 | mNonE10sParent = new media::Parent<media::NonE10s>(); |
2536 | } |
2537 | return mNonE10sParent; |
2538 | } |
2539 | |
2540 | /* static */ |
2541 | void MediaManager::Dispatch(already_AddRefed<Runnable> task) { |
2542 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2542); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2542; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2543 | if (sHasMainThreadShutdown) { |
2544 | // Can't safely delete task here since it may have items with specific |
2545 | // thread-release requirements. |
2546 | // XXXkhuey well then who is supposed to delete it?! We don't signal |
2547 | // that we failed ... |
2548 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2548); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 2548; __attribute__((nomerge)) ::abort(); } while (false); } while (false); |
2549 | return; |
2550 | } |
2551 | NS_ASSERTION(Get(), "MediaManager singleton?")do { if (!(Get())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "MediaManager singleton?" , "Get()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2551); MOZ_PretendNoReturn(); } } while (0); |
2552 | NS_ASSERTION(Get()->mMediaThread, "No thread yet")do { if (!(Get()->mMediaThread)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "No thread yet", "Get()->mMediaThread", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2552); MOZ_PretendNoReturn(); } } while (0); |
2553 | MOZ_ALWAYS_SUCCEEDS(Get()->mMediaThread->Dispatch(std::move(task)))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (Get()->mMediaThread->Dispatch(std::move(task)))), 1))) ), 1))) { } else { do { do { } while (false); MOZ_ReportCrash ("" "NS_SUCCEEDED(Get()->mMediaThread->Dispatch(std::move(task)))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2553); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(Get()->mMediaThread->Dispatch(std::move(task)))" ")"); do { *((volatile int*)__null) = 2553; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); |
2554 | } |
2555 | |
2556 | template <typename MozPromiseType, typename FunctionType> |
2557 | /* static */ |
2558 | RefPtr<MozPromiseType> MediaManager::Dispatch(StaticString aName, |
2559 | FunctionType&& aFunction) { |
2560 | MozPromiseHolder<MozPromiseType> holder; |
2561 | RefPtr<MozPromiseType> promise = holder.Ensure(aName); |
2562 | MediaManager::Dispatch(NS_NewRunnableFunction( |
2563 | aName, [h = std::move(holder), func = std::forward<FunctionType>( |
2564 | aFunction)]() mutable { func(h); })); |
2565 | return promise; |
2566 | } |
2567 | |
2568 | /* static */ |
2569 | nsresult MediaManager::NotifyRecordingStatusChange( |
2570 | nsPIDOMWindowInner* aWindow) { |
2571 | NS_ENSURE_ARG(aWindow)do { if ((__builtin_expect(!!(!(aWindow)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWindow" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2571); return NS_ERROR_INVALID_ARG; } } while (false); |
2572 | |
2573 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
2574 | if (!obs) { |
2575 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Could not get the Observer service for GetUserMedia recording " "notification.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2577) |
2576 | "Could not get the Observer service for GetUserMedia recording "NS_DebugBreak(NS_DEBUG_WARNING, "Could not get the Observer service for GetUserMedia recording " "notification.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2577) |
2577 | "notification.")NS_DebugBreak(NS_DEBUG_WARNING, "Could not get the Observer service for GetUserMedia recording " "notification.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2577); |
2578 | return NS_ERROR_FAILURE; |
2579 | } |
2580 | |
2581 | auto props = MakeRefPtr<nsHashPropertyBag>(); |
2582 | |
2583 | nsCString pageURL; |
2584 | nsCOMPtr<nsIURI> docURI = aWindow->GetDocumentURI(); |
2585 | NS_ENSURE_TRUE(docURI, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(docURI)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "docURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2585); return NS_ERROR_FAILURE; } } while (false); |
2586 | |
2587 | nsresult rv = docURI->GetSpec(pageURL); |
2588 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2588); return rv; } } while (false); |
2589 | |
2590 | NS_ConvertUTF8toUTF16 requestURL(pageURL); |
2591 | |
2592 | props->SetPropertyAsAString(u"requestURL"_ns, requestURL); |
2593 | props->SetPropertyAsInterface(u"window"_ns, aWindow); |
2594 | |
2595 | obs->NotifyObservers(static_cast<nsIPropertyBag2*>(props), |
2596 | "recording-device-events", nullptr); |
2597 | LOG("Sent recording-device-events for url '%s'", pageURL.get()); |
2598 | |
2599 | return NS_OK; |
2600 | } |
2601 | |
2602 | void MediaManager::DeviceListChanged() { |
2603 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2603; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2604 | if (sHasMainThreadShutdown) { |
2605 | return; |
2606 | } |
2607 | // Invalidate immediately to provide an up-to-date device list for future |
2608 | // enumerations on platforms with sane device-list-changed events. |
2609 | InvalidateDeviceCache(); |
2610 | |
2611 | // Wait 200 ms, because |
2612 | // A) on some Windows machines, if we call EnumerateRawDevices immediately |
2613 | // after receiving devicechange event, we'd get an outdated devices list. |
2614 | // B) Waiting helps coalesce multiple calls on us into one, which can happen |
2615 | // if a device with both audio input and output is attached or removed. |
2616 | // We want to react & fire a devicechange event only once in that case. |
2617 | |
2618 | // The wait is extended if another hardware device-list-changed notification |
2619 | // is received to provide the full 200ms for EnumerateRawDevices(). |
2620 | if (mDeviceChangeTimer) { |
2621 | mDeviceChangeTimer->Cancel(); |
2622 | } else { |
2623 | mDeviceChangeTimer = MakeRefPtr<MediaTimer<TimeStamp>>(); |
2624 | } |
2625 | // However, if this would cause a delay of over 1000ms in handling the |
2626 | // oldest unhandled event, then respond now and set the timer to run |
2627 | // EnumerateRawDevices() again in 200ms. |
2628 | auto now = TimeStamp::NowLoRes(); |
2629 | auto enumerateDelay = TimeDuration::FromMilliseconds(200); |
2630 | auto coalescenceLimit = TimeDuration::FromMilliseconds(1000) - enumerateDelay; |
2631 | if (!mUnhandledDeviceChangeTime) { |
2632 | mUnhandledDeviceChangeTime = now; |
2633 | } else if (now - mUnhandledDeviceChangeTime > coalescenceLimit) { |
2634 | HandleDeviceListChanged(); |
2635 | mUnhandledDeviceChangeTime = now; |
2636 | } |
2637 | RefPtr<MediaManager> self = this; |
2638 | mDeviceChangeTimer->WaitFor(enumerateDelay, __func__) |
2639 | ->Then( |
2640 | GetCurrentSerialEventTarget(), __func__, |
2641 | [self, this] { |
2642 | // Invalidate again for the sake of platforms with inconsistent |
2643 | // timing between device-list-changed notification and enumeration. |
2644 | InvalidateDeviceCache(); |
2645 | |
2646 | mUnhandledDeviceChangeTime = TimeStamp(); |
2647 | HandleDeviceListChanged(); |
2648 | }, |
2649 | [] { /* Timer was canceled by us, or we're in shutdown. */ }); |
2650 | } |
2651 | |
2652 | void MediaManager::EnsureNoPlaceholdersInDeviceCache() { |
2653 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2653); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2653; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2654 | |
2655 | if (mPhysicalDevices) { |
2656 | // Invalidate the list if there is a placeholder |
2657 | for (const auto& device : *mPhysicalDevices) { |
2658 | if (device->mIsPlaceholder) { |
2659 | InvalidateDeviceCache(); |
2660 | break; |
2661 | } |
2662 | } |
2663 | } |
2664 | } |
2665 | |
2666 | void MediaManager::InvalidateDeviceCache() { |
2667 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2667); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2667; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2668 | |
2669 | mPhysicalDevices = nullptr; |
2670 | // Disconnect any in-progress enumeration, which may now be out of date, |
2671 | // from updating mPhysicalDevices or resolving future device request |
2672 | // promises. |
2673 | mPendingDevicesPromises = nullptr; |
2674 | } |
2675 | |
2676 | void MediaManager::HandleDeviceListChanged() { |
2677 | mDeviceListChangeEvent.Notify(); |
2678 | |
2679 | GetPhysicalDevices()->Then( |
2680 | GetCurrentSerialEventTarget(), __func__, |
2681 | [self = RefPtr(this), this](RefPtr<const MediaDeviceSetRefCnt> aDevices) { |
2682 | if (!MediaManager::GetIfExists()) { |
2683 | return; |
2684 | } |
2685 | |
2686 | nsTHashSet<nsString> deviceIDs; |
2687 | for (const auto& device : *aDevices) { |
2688 | deviceIDs.Insert(device->mRawID); |
2689 | } |
2690 | // For any real removed cameras or microphones, notify their |
2691 | // listeners cleanly that the source has stopped, so JS knows and |
2692 | // usage indicators update. |
2693 | // First collect the listeners in an array to stop them after |
2694 | // iterating the hashtable. The StopRawID() method indirectly |
2695 | // modifies the mActiveWindows and would assert-crash if the |
2696 | // iterator were active while the table is being enumerated. |
2697 | const auto windowListeners = ToArray(mActiveWindows.Values()); |
2698 | for (const RefPtr<GetUserMediaWindowListener>& l : windowListeners) { |
2699 | const auto activeDevices = l->GetDevices(); |
2700 | for (const RefPtr<LocalMediaDevice>& device : *activeDevices) { |
2701 | if (device->IsFake()) { |
2702 | continue; |
2703 | } |
2704 | MediaSourceEnum mediaSource = device->GetMediaSource(); |
2705 | if (mediaSource != MediaSourceEnum::Microphone && |
2706 | mediaSource != MediaSourceEnum::Camera) { |
2707 | continue; |
2708 | } |
2709 | if (!deviceIDs.Contains(device->RawID())) { |
2710 | // Device has been removed |
2711 | l->StopRawID(device->RawID()); |
2712 | } |
2713 | } |
2714 | } |
2715 | }, |
2716 | [](RefPtr<MediaMgrError>&& reason) { |
2717 | MOZ_ASSERT_UNREACHABLE("EnumerateRawDevices does not reject")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "EnumerateRawDevices does not reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "EnumerateRawDevices does not reject" ")"); do { *((volatile int*)__null) = 2717; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2718 | }); |
2719 | } |
2720 | |
2721 | size_t MediaManager::AddTaskAndGetCount(uint64_t aWindowID, |
2722 | const nsAString& aCallID, |
2723 | RefPtr<GetUserMediaTask> aTask) { |
2724 | // Store the task w/callbacks. |
2725 | mActiveCallbacks.InsertOrUpdate(aCallID, std::move(aTask)); |
2726 | |
2727 | // Add a WindowID cross-reference so OnNavigation can tear things down |
2728 | nsTArray<nsString>* const array = mCallIds.GetOrInsertNew(aWindowID); |
2729 | array->AppendElement(aCallID); |
2730 | |
2731 | return array->Length(); |
2732 | } |
2733 | |
2734 | RefPtr<GetUserMediaTask> MediaManager::TakeGetUserMediaTask( |
2735 | const nsAString& aCallID) { |
2736 | RefPtr<GetUserMediaTask> task; |
2737 | mActiveCallbacks.Remove(aCallID, getter_AddRefs(task)); |
2738 | if (!task) { |
2739 | return nullptr; |
2740 | } |
2741 | nsTArray<nsString>* array; |
2742 | mCallIds.Get(task->GetWindowID(), &array); |
2743 | MOZ_ASSERT(array)do { static_assert( mozilla::detail::AssertionConditionType< decltype(array)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(array))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("array", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2743); AnnotateMozCrashReason("MOZ_ASSERT" "(" "array" ")") ; do { *((volatile int*)__null) = 2743; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2744 | array->RemoveElement(aCallID); |
2745 | return task; |
2746 | } |
2747 | |
2748 | void MediaManager::NotifyAllowed(const nsString& aCallID, |
2749 | const LocalMediaDeviceSet& aDevices) { |
2750 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
2751 | nsCOMPtr<nsIMutableArray> devicesCopy = nsArray::Create(); |
2752 | for (const auto& device : aDevices) { |
2753 | nsresult rv = devicesCopy->AppendElement(device); |
2754 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2754)) { |
2755 | obs->NotifyObservers(nullptr, "getUserMedia:response:deny", |
2756 | aCallID.get()); |
2757 | return; |
2758 | } |
2759 | } |
2760 | obs->NotifyObservers(devicesCopy, "getUserMedia:privileged:allow", |
2761 | aCallID.get()); |
2762 | } |
2763 | |
2764 | nsresult MediaManager::GenerateUUID(nsAString& aResult) { |
2765 | nsresult rv; |
2766 | nsCOMPtr<nsIUUIDGenerator> uuidgen = |
2767 | do_GetService("@mozilla.org/uuid-generator;1", &rv); |
2768 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2768); return rv; } } while (false); |
2769 | |
2770 | // Generate a call ID. |
2771 | nsID id; |
2772 | rv = uuidgen->GenerateUUIDInPlace(&id); |
2773 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2773); return rv; } } while (false); |
2774 | |
2775 | char buffer[NSID_LENGTH39]; |
2776 | id.ToProvidedString(buffer); |
2777 | aResult.Assign(NS_ConvertUTF8toUTF16(buffer)); |
2778 | return NS_OK; |
2779 | } |
2780 | |
2781 | enum class GetUserMediaSecurityState { |
2782 | Other = 0, |
2783 | HTTPS = 1, |
2784 | File = 2, |
2785 | App = 3, |
2786 | Localhost = 4, |
2787 | Loop = 5, |
2788 | Privileged = 6 |
2789 | }; |
2790 | |
2791 | /** |
2792 | * This function is used in getUserMedia when privacy.resistFingerprinting is |
2793 | * true. Only mediaSource of audio/video constraint will be kept. On mobile |
2794 | * facing mode is also kept. |
2795 | */ |
2796 | static void ReduceConstraint( |
2797 | OwningBooleanOrMediaTrackConstraints& aConstraint) { |
2798 | // Not requesting stream. |
2799 | if (!MediaManager::IsOn(aConstraint)) { |
2800 | return; |
2801 | } |
2802 | |
2803 | // It looks like {audio: true}, do nothing. |
2804 | if (!aConstraint.IsMediaTrackConstraints()) { |
2805 | return; |
2806 | } |
2807 | |
2808 | // Keep mediaSource. |
2809 | Maybe<nsString> mediaSource; |
2810 | if (aConstraint.GetAsMediaTrackConstraints().mMediaSource.WasPassed()) { |
2811 | mediaSource = |
2812 | Some(aConstraint.GetAsMediaTrackConstraints().mMediaSource.Value()); |
2813 | } |
2814 | |
2815 | Maybe<OwningStringOrStringSequenceOrConstrainDOMStringParameters> facingMode; |
2816 | if (aConstraint.GetAsMediaTrackConstraints().mFacingMode.WasPassed()) { |
2817 | facingMode = |
2818 | Some(aConstraint.GetAsMediaTrackConstraints().mFacingMode.Value()); |
2819 | } |
2820 | |
2821 | aConstraint.Uninit(); |
2822 | if (mediaSource) { |
2823 | aConstraint.SetAsMediaTrackConstraints().mMediaSource.Construct( |
2824 | *mediaSource); |
2825 | } else { |
2826 | Unused << aConstraint.SetAsMediaTrackConstraints(); |
2827 | } |
2828 | |
2829 | #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) |
2830 | if (facingMode) { |
2831 | aConstraint.SetAsMediaTrackConstraints().mFacingMode.Construct(*facingMode); |
2832 | } else { |
2833 | Unused << aConstraint.SetAsMediaTrackConstraints(); |
2834 | } |
2835 | #endif |
2836 | } |
2837 | |
2838 | /** |
2839 | * The entry point for this file. A call from Navigator::mozGetUserMedia |
2840 | * will end up here. MediaManager is a singleton that is responsible |
2841 | * for handling all incoming getUserMedia calls from every window. |
2842 | */ |
2843 | RefPtr<MediaManager::StreamPromise> MediaManager::GetUserMedia( |
2844 | nsPIDOMWindowInner* aWindow, |
2845 | const MediaStreamConstraints& aConstraintsPassedIn, |
2846 | CallerType aCallerType) { |
2847 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2847; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2848 | MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")" ); do { *((volatile int*)__null) = 2848; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2849 | uint64_t windowID = aWindow->WindowID(); |
2850 | |
2851 | MediaStreamConstraints c(aConstraintsPassedIn); // use a modifiable copy |
2852 | |
2853 | if (sHasMainThreadShutdown) { |
2854 | return StreamPromise::CreateAndReject( |
2855 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError, |
2856 | "In shutdown"), |
2857 | __func__); |
2858 | } |
2859 | |
2860 | // Determine permissions early (while we still have a stack). |
2861 | |
2862 | nsIURI* docURI = aWindow->GetDocumentURI(); |
2863 | if (!docURI) { |
2864 | return StreamPromise::CreateAndReject( |
2865 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), __func__); |
2866 | } |
2867 | bool isChrome = (aCallerType == CallerType::System); |
2868 | bool privileged = |
2869 | isChrome || |
2870 | Preferences::GetBool("media.navigator.permission.disabled", false); |
2871 | bool isSecure = aWindow->IsSecureContext(); |
2872 | bool isHandlingUserInput = UserActivation::IsHandlingUserInput(); |
2873 | nsCString host; |
2874 | nsresult rv = docURI->GetHost(host); |
Value stored to 'rv' during its initialization is never read | |
2875 | |
2876 | nsCOMPtr<nsIPrincipal> principal = |
2877 | nsGlobalWindowInner::Cast(aWindow)->GetPrincipal(); |
2878 | if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2878)) { |
2879 | return StreamPromise::CreateAndReject( |
2880 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
2881 | __func__); |
2882 | } |
2883 | |
2884 | Document* doc = aWindow->GetExtantDoc(); |
2885 | if (NS_WARN_IF(!doc)NS_warn_if_impl(!doc, "!doc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2885)) { |
2886 | return StreamPromise::CreateAndReject( |
2887 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
2888 | __func__); |
2889 | } |
2890 | |
2891 | // Disallow access to null principal pages and http pages (unless pref) |
2892 | if (principal->GetIsNullPrincipal() || |
2893 | !(isSecure || StaticPrefs::media_getusermedia_insecure_enabled())) { |
2894 | return StreamPromise::CreateAndReject( |
2895 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
2896 | __func__); |
2897 | } |
2898 | |
2899 | // This principal needs to be sent to different threads and so via IPC. |
2900 | // For this reason it's better to convert it to PrincipalInfo right now. |
2901 | ipc::PrincipalInfo principalInfo; |
2902 | rv = PrincipalToPrincipalInfo(principal, &principalInfo); |
2903 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2903)) { |
2904 | return StreamPromise::CreateAndReject( |
2905 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
2906 | __func__); |
2907 | } |
2908 | |
2909 | const bool resistFingerprinting = |
2910 | !isChrome && doc->ShouldResistFingerprinting(RFPTarget::MediaDevices); |
2911 | if (resistFingerprinting) { |
2912 | ReduceConstraint(c.mVideo); |
2913 | ReduceConstraint(c.mAudio); |
2914 | } |
2915 | |
2916 | if (!Preferences::GetBool("media.navigator.video.enabled", true)) { |
2917 | c.mVideo.SetAsBoolean() = false; |
2918 | } |
2919 | |
2920 | MediaSourceEnum videoType = MediaSourceEnum::Other; // none |
2921 | MediaSourceEnum audioType = MediaSourceEnum::Other; // none |
2922 | |
2923 | if (c.mVideo.IsMediaTrackConstraints()) { |
2924 | auto& vc = c.mVideo.GetAsMediaTrackConstraints(); |
2925 | if (!vc.mMediaSource.WasPassed()) { |
2926 | vc.mMediaSource.Construct().AssignASCII( |
2927 | dom::GetEnumString(MediaSourceEnum::Camera)); |
2928 | } |
2929 | videoType = dom::StringToEnum<MediaSourceEnum>(vc.mMediaSource.Value()) |
2930 | .valueOr(MediaSourceEnum::Other); |
2931 | Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE, |
2932 | (uint32_t)videoType); |
2933 | switch (videoType) { |
2934 | case MediaSourceEnum::Camera: |
2935 | break; |
2936 | |
2937 | case MediaSourceEnum::Browser: |
2938 | // If no window id is passed in then default to the caller's window. |
2939 | // Functional defaults are helpful in tests, but also a natural outcome |
2940 | // of the constraints API's limited semantics for requiring input. |
2941 | if (!vc.mBrowserWindow.WasPassed()) { |
2942 | nsPIDOMWindowOuter* outer = aWindow->GetOuterWindow(); |
2943 | vc.mBrowserWindow.Construct(outer->WindowID()); |
2944 | } |
2945 | [[fallthrough]]; |
2946 | case MediaSourceEnum::Screen: |
2947 | case MediaSourceEnum::Window: |
2948 | // Deny screensharing request if support is disabled, or |
2949 | // the requesting document is not from a host on the whitelist. |
2950 | if (!Preferences::GetBool( |
2951 | ((videoType == MediaSourceEnum::Browser) |
2952 | ? "media.getusermedia.browser.enabled" |
2953 | : "media.getusermedia.screensharing.enabled"), |
2954 | false) || |
2955 | (!privileged && !aWindow->IsSecureContext())) { |
2956 | return StreamPromise::CreateAndReject( |
2957 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
2958 | __func__); |
2959 | } |
2960 | break; |
2961 | |
2962 | case MediaSourceEnum::Microphone: |
2963 | case MediaSourceEnum::Other: |
2964 | default: { |
2965 | return StreamPromise::CreateAndReject( |
2966 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::OverconstrainedError, |
2967 | "", u"mediaSource"_ns), |
2968 | __func__); |
2969 | } |
2970 | } |
2971 | |
2972 | if (!privileged) { |
2973 | // Only allow privileged content to explicitly pick full-screen, |
2974 | // application or tabsharing, since these modes are still available for |
2975 | // testing. All others get "Window" (*) sharing. |
2976 | // |
2977 | // *) We overload "Window" with the new default getDisplayMedia spec- |
2978 | // mandated behavior of not influencing user-choice, which we currently |
2979 | // implement as a list containing BOTH windows AND screen(s). |
2980 | // |
2981 | // Notes on why we chose "Window" as the one to overload. Two reasons: |
2982 | // |
2983 | // 1. It's the closest logically & behaviorally (multi-choice, no default) |
2984 | // 2. Screen is still useful in tests (implicit default is entire screen) |
2985 | // |
2986 | // For UX reasons we don't want "Entire Screen" to be the first/default |
2987 | // choice (in our code first=default). It's a "scary" source that comes |
2988 | // with complicated warnings on-top that would be confusing as the first |
2989 | // thing people see, and also deserves to be listed as last resort for |
2990 | // privacy reasons. |
2991 | |
2992 | if (videoType == MediaSourceEnum::Screen || |
2993 | videoType == MediaSourceEnum::Browser) { |
2994 | videoType = MediaSourceEnum::Window; |
2995 | vc.mMediaSource.Value().AssignASCII(dom::GetEnumString(videoType)); |
2996 | } |
2997 | // only allow privileged content to set the window id |
2998 | if (vc.mBrowserWindow.WasPassed()) { |
2999 | vc.mBrowserWindow.Value() = -1; |
3000 | } |
3001 | if (vc.mAdvanced.WasPassed()) { |
3002 | for (MediaTrackConstraintSet& cs : vc.mAdvanced.Value()) { |
3003 | if (cs.mBrowserWindow.WasPassed()) { |
3004 | cs.mBrowserWindow.Value() = -1; |
3005 | } |
3006 | } |
3007 | } |
3008 | } |
3009 | } else if (IsOn(c.mVideo)) { |
3010 | videoType = MediaSourceEnum::Camera; |
3011 | Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE, |
3012 | (uint32_t)videoType); |
3013 | } |
3014 | |
3015 | if (c.mAudio.IsMediaTrackConstraints()) { |
3016 | auto& ac = c.mAudio.GetAsMediaTrackConstraints(); |
3017 | if (!ac.mMediaSource.WasPassed()) { |
3018 | ac.mMediaSource.Construct(NS_ConvertASCIItoUTF16( |
3019 | dom::GetEnumString(MediaSourceEnum::Microphone))); |
3020 | } |
3021 | audioType = dom::StringToEnum<MediaSourceEnum>(ac.mMediaSource.Value()) |
3022 | .valueOr(MediaSourceEnum::Other); |
3023 | Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE, |
3024 | (uint32_t)audioType); |
3025 | |
3026 | switch (audioType) { |
3027 | case MediaSourceEnum::Microphone: |
3028 | break; |
3029 | |
3030 | case MediaSourceEnum::AudioCapture: |
3031 | // Only enable AudioCapture if the pref is enabled. If it's not, we can |
3032 | // deny right away. |
3033 | if (!Preferences::GetBool("media.getusermedia.audio.capture.enabled")) { |
3034 | return StreamPromise::CreateAndReject( |
3035 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
3036 | __func__); |
3037 | } |
3038 | break; |
3039 | |
3040 | case MediaSourceEnum::Other: |
3041 | default: { |
3042 | return StreamPromise::CreateAndReject( |
3043 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::OverconstrainedError, |
3044 | "", u"mediaSource"_ns), |
3045 | __func__); |
3046 | } |
3047 | } |
3048 | } else if (IsOn(c.mAudio)) { |
3049 | audioType = MediaSourceEnum::Microphone; |
3050 | Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE, |
3051 | (uint32_t)audioType); |
3052 | } |
3053 | |
3054 | // Create a window listener if it doesn't already exist. |
3055 | RefPtr<GetUserMediaWindowListener> windowListener = |
3056 | GetOrMakeWindowListener(aWindow); |
3057 | MOZ_ASSERT(windowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3057); AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener" ")"); do { *((volatile int*)__null) = 3057; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3058 | // Create an inactive DeviceListener to act as a placeholder, so the |
3059 | // window listener doesn't clean itself up until we're done. |
3060 | auto placeholderListener = MakeRefPtr<DeviceListener>(); |
3061 | windowListener->Register(placeholderListener); |
3062 | |
3063 | { // Check Permissions Policy. Reject if a requested feature is disabled. |
3064 | bool disabled = !IsOn(c.mAudio) && !IsOn(c.mVideo); |
3065 | if (IsOn(c.mAudio)) { |
3066 | if (audioType == MediaSourceEnum::Microphone) { |
3067 | if (Preferences::GetBool("media.getusermedia.microphone.deny", false) || |
3068 | !FeaturePolicyUtils::IsFeatureAllowed(doc, u"microphone"_ns)) { |
3069 | disabled = true; |
3070 | } |
3071 | } else if (!FeaturePolicyUtils::IsFeatureAllowed(doc, |
3072 | u"display-capture"_ns)) { |
3073 | disabled = true; |
3074 | } |
3075 | } |
3076 | if (IsOn(c.mVideo)) { |
3077 | if (videoType == MediaSourceEnum::Camera) { |
3078 | if (Preferences::GetBool("media.getusermedia.camera.deny", false) || |
3079 | !FeaturePolicyUtils::IsFeatureAllowed(doc, u"camera"_ns)) { |
3080 | disabled = true; |
3081 | } |
3082 | } else if (!FeaturePolicyUtils::IsFeatureAllowed(doc, |
3083 | u"display-capture"_ns)) { |
3084 | disabled = true; |
3085 | } |
3086 | } |
3087 | |
3088 | if (disabled) { |
3089 | placeholderListener->Stop(); |
3090 | return StreamPromise::CreateAndReject( |
3091 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
3092 | __func__); |
3093 | } |
3094 | } |
3095 | |
3096 | // Get list of all devices, with origin-specific device ids. |
3097 | |
3098 | MediaEnginePrefs prefs = mPrefs; |
3099 | |
3100 | nsString callID; |
3101 | rv = GenerateUUID(callID); |
3102 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3102); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3102; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3103 | |
3104 | bool hasVideo = videoType != MediaSourceEnum::Other; |
3105 | bool hasAudio = audioType != MediaSourceEnum::Other; |
3106 | |
3107 | // Handle fake requests from content. For gUM we don't consider resist |
3108 | // fingerprinting as users should be prompted anyway. |
3109 | bool forceFakes = c.mFake.WasPassed() && c.mFake.Value(); |
3110 | // fake:true is effective only for microphone and camera devices, so |
3111 | // permission must be requested for screen capture even if fake:true is set. |
3112 | bool hasOnlyForcedFakes = |
3113 | forceFakes && (!hasVideo || videoType == MediaSourceEnum::Camera) && |
3114 | (!hasAudio || audioType == MediaSourceEnum::Microphone); |
3115 | bool askPermission = |
3116 | (!privileged || |
3117 | Preferences::GetBool("media.navigator.permission.force")) && |
3118 | (!hasOnlyForcedFakes || |
3119 | Preferences::GetBool("media.navigator.permission.fake")); |
3120 | |
3121 | LOG("%s: Preparing to enumerate devices. windowId=%" PRIu64"l" "u" |
3122 | ", videoType=%" PRIu8"u" ", audioType=%" PRIu8"u" |
3123 | ", forceFakes=%s, askPermission=%s", |
3124 | __func__, windowID, static_cast<uint8_t>(videoType), |
3125 | static_cast<uint8_t>(audioType), forceFakes ? "true" : "false", |
3126 | askPermission ? "true" : "false"); |
3127 | |
3128 | EnumerationFlags flags = EnumerationFlag::AllowPermissionRequest; |
3129 | if (forceFakes) { |
3130 | flags += EnumerationFlag::ForceFakes; |
3131 | } |
3132 | RefPtr<MediaManager> self = this; |
3133 | return EnumerateDevicesImpl( |
3134 | aWindow, CreateEnumerationParams(videoType, audioType, flags)) |
3135 | ->Then( |
3136 | GetCurrentSerialEventTarget(), __func__, |
3137 | [self, windowID, c, windowListener, |
3138 | aCallerType](RefPtr<LocalMediaDeviceSetRefCnt> aDevices) { |
3139 | LOG("GetUserMedia: post enumeration promise success callback " |
3140 | "starting"); |
3141 | // Ensure that our windowID is still good. |
3142 | RefPtr<nsPIDOMWindowInner> window = |
3143 | nsGlobalWindowInner::GetInnerWindowWithId(windowID); |
3144 | if (!window || !self->IsWindowListenerStillActive(windowListener)) { |
3145 | LOG("GetUserMedia: bad window (%" PRIu64"l" "u" |
3146 | ") in post enumeration success callback!", |
3147 | windowID); |
3148 | return LocalDeviceSetPromise::CreateAndReject( |
3149 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3150 | __func__); |
3151 | } |
3152 | // Apply any constraints. This modifies the passed-in list. |
3153 | return self->SelectSettings(c, aCallerType, std::move(aDevices)); |
3154 | }, |
3155 | [](RefPtr<MediaMgrError>&& aError) { |
3156 | LOG("GetUserMedia: post enumeration EnumerateDevicesImpl " |
3157 | "failure callback called!"); |
3158 | return LocalDeviceSetPromise::CreateAndReject(std::move(aError), |
3159 | __func__); |
3160 | }) |
3161 | ->Then( |
3162 | GetCurrentSerialEventTarget(), __func__, |
3163 | [self, windowID, c, windowListener, placeholderListener, hasAudio, |
3164 | hasVideo, askPermission, prefs, isSecure, isHandlingUserInput, |
3165 | callID, principalInfo, aCallerType, resistFingerprinting, |
3166 | audioType](RefPtr<LocalMediaDeviceSetRefCnt> aDevices) mutable { |
3167 | LOG("GetUserMedia: starting post enumeration promise2 success " |
3168 | "callback!"); |
3169 | |
3170 | // Ensure that the window is still good. |
3171 | RefPtr<nsPIDOMWindowInner> window = |
3172 | nsGlobalWindowInner::GetInnerWindowWithId(windowID); |
3173 | if (!window || !self->IsWindowListenerStillActive(windowListener)) { |
3174 | LOG("GetUserMedia: bad window (%" PRIu64"l" "u" |
3175 | ") in post enumeration success callback 2!", |
3176 | windowID); |
3177 | placeholderListener->Stop(); |
3178 | return StreamPromise::CreateAndReject( |
3179 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3180 | __func__); |
3181 | } |
3182 | if (!aDevices->Length()) { |
3183 | LOG("GetUserMedia: no devices found in post enumeration promise2 " |
3184 | "success callback! Calling error handler!"); |
3185 | placeholderListener->Stop(); |
3186 | // When privacy.resistFingerprinting = true, no |
3187 | // available device implies content script is requesting |
3188 | // a fake device, so report NotAllowedError. |
3189 | auto error = resistFingerprinting |
3190 | ? MediaMgrError::Name::NotAllowedError |
3191 | : MediaMgrError::Name::NotFoundError; |
3192 | return StreamPromise::CreateAndReject( |
3193 | MakeRefPtr<MediaMgrError>(error), __func__); |
3194 | } |
3195 | |
3196 | // Time to start devices. Create the necessary device listeners and |
3197 | // remove the placeholder. |
3198 | RefPtr<DeviceListener> audioListener; |
3199 | RefPtr<DeviceListener> videoListener; |
3200 | if (hasAudio) { |
3201 | audioListener = MakeRefPtr<DeviceListener>(); |
3202 | windowListener->Register(audioListener); |
3203 | } |
3204 | if (hasVideo) { |
3205 | videoListener = MakeRefPtr<DeviceListener>(); |
3206 | windowListener->Register(videoListener); |
3207 | } |
3208 | placeholderListener->Stop(); |
3209 | |
3210 | bool focusSource = mozilla::Preferences::GetBool( |
3211 | "media.getusermedia.window.focus_source.enabled", true); |
3212 | |
3213 | // Incremental hack to compile. To be replaced by deeper |
3214 | // refactoring. MediaManager allows |
3215 | // "neither-resolve-nor-reject" semantics, so we cannot |
3216 | // use MozPromiseHolder here. |
3217 | MozPromiseHolder<StreamPromise> holder; |
3218 | RefPtr<StreamPromise> p = holder.Ensure(__func__); |
3219 | |
3220 | // Pass callbacks and listeners along to GetUserMediaStreamTask. |
3221 | auto task = MakeRefPtr<GetUserMediaStreamTask>( |
3222 | c, std::move(holder), windowID, std::move(windowListener), |
3223 | std::move(audioListener), std::move(videoListener), prefs, |
3224 | principalInfo, aCallerType, focusSource); |
3225 | |
3226 | // It is time to ask for user permission, prime voice processing |
3227 | // now. Use a local lambda to enable a guard pattern. |
3228 | [&] { |
3229 | if (audioType != MediaSourceEnum::Microphone) { |
3230 | return; |
3231 | } |
3232 | |
3233 | if (!StaticPrefs:: |
3234 | media_getusermedia_microphone_voice_stream_priming_enabled() || |
3235 | !StaticPrefs:: |
3236 | media_getusermedia_microphone_prefer_voice_stream_with_processing_enabled()) { |
3237 | return; |
3238 | } |
3239 | |
3240 | if (const auto fc = FlattenedConstraints( |
3241 | NormalizedConstraints(GetInvariant(c.mAudio))); |
3242 | !fc.mEchoCancellation.Get(prefs.mAecOn) && |
3243 | !fc.mAutoGainControl.Get(prefs.mAgcOn && prefs.mAecOn) && |
3244 | !fc.mNoiseSuppression.Get(prefs.mNoiseOn && prefs.mAecOn)) { |
3245 | return; |
3246 | } |
3247 | |
3248 | if (GetPersistentPermissions(windowID) |
3249 | .map([](auto&& aState) { |
3250 | return aState.mMicrophonePermission == |
3251 | PersistentPermissionState::Deny; |
3252 | }) |
3253 | .unwrapOr(true)) { |
3254 | return; |
3255 | } |
3256 | |
3257 | task->PrimeVoiceProcessing(); |
3258 | }(); |
3259 | |
3260 | size_t taskCount = |
3261 | self->AddTaskAndGetCount(windowID, callID, std::move(task)); |
3262 | |
3263 | if (!askPermission) { |
3264 | self->NotifyAllowed(callID, *aDevices); |
3265 | } else { |
3266 | auto req = MakeRefPtr<GetUserMediaRequest>( |
3267 | window, callID, std::move(aDevices), c, isSecure, |
3268 | isHandlingUserInput); |
3269 | if (!Preferences::GetBool("media.navigator.permission.force") && |
3270 | taskCount > 1) { |
3271 | // there is at least 1 pending gUM request |
3272 | // For the scarySources test case, always send the |
3273 | // request |
3274 | self->mPendingGUMRequest.AppendElement(req.forget()); |
3275 | } else { |
3276 | nsCOMPtr<nsIObserverService> obs = |
3277 | services::GetObserverService(); |
3278 | obs->NotifyObservers(req, "getUserMedia:request", nullptr); |
3279 | } |
3280 | } |
3281 | #ifdef MOZ_WEBRTC1 |
3282 | self->mLogHandle = EnsureWebrtcLogging(); |
3283 | #endif |
3284 | return p; |
3285 | }, |
3286 | [placeholderListener](RefPtr<MediaMgrError>&& aError) { |
3287 | LOG("GetUserMedia: post enumeration SelectSettings failure " |
3288 | "callback called!"); |
3289 | placeholderListener->Stop(); |
3290 | return StreamPromise::CreateAndReject(std::move(aError), __func__); |
3291 | }); |
3292 | }; |
3293 | |
3294 | RefPtr<LocalDeviceSetPromise> MediaManager::AnonymizeDevices( |
3295 | nsPIDOMWindowInner* aWindow, RefPtr<const MediaDeviceSetRefCnt> aDevices) { |
3296 | // Get an origin-key (for either regular or private browsing). |
3297 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3297; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3298 | uint64_t windowId = aWindow->WindowID(); |
3299 | nsCOMPtr<nsIPrincipal> principal = |
3300 | nsGlobalWindowInner::Cast(aWindow)->GetPrincipal(); |
3301 | MOZ_ASSERT(principal)do { static_assert( mozilla::detail::AssertionConditionType< decltype(principal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(principal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal" ")" ); do { *((volatile int*)__null) = 3301; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3302 | ipc::PrincipalInfo principalInfo; |
3303 | nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo); |
3304 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3304)) { |
3305 | return LocalDeviceSetPromise::CreateAndReject( |
3306 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
3307 | __func__); |
3308 | } |
3309 | bool resistFingerprinting = |
3310 | aWindow->AsGlobal()->ShouldResistFingerprinting(RFPTarget::MediaDevices); |
3311 | bool persist = |
3312 | IsActivelyCapturingOrHasAPermission(windowId) && !resistFingerprinting; |
3313 | return media::GetPrincipalKey(principalInfo, persist) |
3314 | ->Then( |
3315 | GetMainThreadSerialEventTarget(), __func__, |
3316 | [rawDevices = std::move(aDevices), windowId, |
3317 | resistFingerprinting](const nsCString& aOriginKey) { |
3318 | MOZ_ASSERT(!aOriginKey.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aOriginKey.IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aOriginKey.IsEmpty()))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!aOriginKey.IsEmpty()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOriginKey.IsEmpty()" ")"); do { *((volatile int*)__null) = 3318; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3319 | RefPtr anonymized = new LocalMediaDeviceSetRefCnt(); |
3320 | for (const RefPtr<MediaDevice>& device : *rawDevices) { |
3321 | nsString name = device->mRawName; |
3322 | if (name.Find(u"AirPods"_ns) != -1) { |
3323 | name = u"AirPods"_ns; |
3324 | } |
3325 | |
3326 | nsString id = device->mRawID; |
3327 | if (resistFingerprinting) { |
3328 | nsRFPService::GetMediaDeviceName(name, device->mKind); |
3329 | id = name; |
3330 | id.AppendInt(windowId); |
3331 | } |
3332 | // An empty id represents a virtual default device, for which |
3333 | // the exposed deviceId is the empty string. |
3334 | if (!id.IsEmpty()) { |
3335 | nsContentUtils::AnonymizeId(id, aOriginKey); |
3336 | } |
3337 | |
3338 | nsString groupId = device->mRawGroupID; |
3339 | if (resistFingerprinting) { |
3340 | nsRFPService::GetMediaDeviceGroup(groupId, device->mKind); |
3341 | } |
3342 | // Use window id to salt group id in order to make it session |
3343 | // based as required by the spec. This does not provide unique |
3344 | // group ids through out a browser restart. However, this is not |
3345 | // against the spec. Furthermore, since device ids are the same |
3346 | // after a browser restart the fingerprint is not bigger. |
3347 | groupId.AppendInt(windowId); |
3348 | nsContentUtils::AnonymizeId(groupId, aOriginKey); |
3349 | anonymized->EmplaceBack( |
3350 | new LocalMediaDevice(device, id, groupId, name)); |
3351 | } |
3352 | return LocalDeviceSetPromise::CreateAndResolve(anonymized, |
3353 | __func__); |
3354 | }, |
3355 | [](nsresult rs) { |
3356 | NS_WARNING("AnonymizeDevices failed to get Principal Key")NS_DebugBreak(NS_DEBUG_WARNING, "AnonymizeDevices failed to get Principal Key" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3356); |
3357 | return LocalDeviceSetPromise::CreateAndReject( |
3358 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3359 | __func__); |
3360 | }); |
3361 | } |
3362 | |
3363 | RefPtr<LocalDeviceSetPromise> MediaManager::EnumerateDevicesImpl( |
3364 | nsPIDOMWindowInner* aWindow, EnumerationParams aParams) { |
3365 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3365; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3366 | |
3367 | uint64_t windowId = aWindow->WindowID(); |
3368 | LOG("%s: windowId=%" PRIu64"l" "u" ", aVideoInputType=%" PRIu8"u" |
3369 | ", aAudioInputType=%" PRIu8"u", |
3370 | __func__, windowId, static_cast<uint8_t>(aParams.VideoInputType()), |
3371 | static_cast<uint8_t>(aParams.AudioInputType())); |
3372 | |
3373 | // To get a device list anonymized for a particular origin, we must: |
3374 | // 1. Get the raw devices list |
3375 | // 2. Anonymize the raw list with an origin-key. |
3376 | |
3377 | // Add the window id here to check for that and abort silently if no longer |
3378 | // exists. |
3379 | RefPtr<GetUserMediaWindowListener> windowListener = |
3380 | GetOrMakeWindowListener(aWindow); |
3381 | MOZ_ASSERT(windowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener" ")"); do { *((volatile int*)__null) = 3381; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3382 | // Create an inactive DeviceListener to act as a placeholder, so the |
3383 | // window listener doesn't clean itself up until we're done. |
3384 | auto placeholderListener = MakeRefPtr<DeviceListener>(); |
3385 | windowListener->Register(placeholderListener); |
3386 | |
3387 | return MaybeRequestPermissionAndEnumerateRawDevices(std::move(aParams)) |
3388 | ->Then( |
3389 | GetMainThreadSerialEventTarget(), __func__, |
3390 | [self = RefPtr(this), this, window = nsCOMPtr(aWindow), |
3391 | placeholderListener](RefPtr<MediaDeviceSetRefCnt> aDevices) mutable { |
3392 | // Only run if window is still on our active list. |
3393 | MediaManager* mgr = MediaManager::GetIfExists(); |
3394 | if (!mgr || placeholderListener->Stopped()) { |
3395 | // The listener has already been removed if the window is no |
3396 | // longer active. |
3397 | return LocalDeviceSetPromise::CreateAndReject( |
3398 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3399 | __func__); |
3400 | } |
3401 | MOZ_ASSERT(mgr->IsWindowStillActive(window->WindowID()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(mgr->IsWindowStillActive(window->WindowID()))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mgr->IsWindowStillActive(window->WindowID()))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mgr->IsWindowStillActive(window->WindowID())" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3401); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mgr->IsWindowStillActive(window->WindowID())" ")"); do { *((volatile int*)__null) = 3401; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3402 | placeholderListener->Stop(); |
3403 | return AnonymizeDevices(window, aDevices); |
3404 | }, |
3405 | [placeholderListener](RefPtr<MediaMgrError>&& aError) { |
3406 | // EnumerateDevicesImpl may fail if a new doc has been set, in which |
3407 | // case the OnNavigation() method should have removed all previous |
3408 | // active listeners, or if a platform device access request was not |
3409 | // granted. |
3410 | placeholderListener->Stop(); |
3411 | return LocalDeviceSetPromise::CreateAndReject(std::move(aError), |
3412 | __func__); |
3413 | }); |
3414 | } |
3415 | |
3416 | RefPtr<LocalDevicePromise> MediaManager::SelectAudioOutput( |
3417 | nsPIDOMWindowInner* aWindow, const dom::AudioOutputOptions& aOptions, |
3418 | CallerType aCallerType) { |
3419 | bool isHandlingUserInput = UserActivation::IsHandlingUserInput(); |
3420 | nsCOMPtr<nsIPrincipal> principal = |
3421 | nsGlobalWindowInner::Cast(aWindow)->GetPrincipal(); |
3422 | if (!FeaturePolicyUtils::IsFeatureAllowed(aWindow->GetExtantDoc(), |
3423 | u"speaker-selection"_ns)) { |
3424 | return LocalDevicePromise::CreateAndReject( |
3425 | MakeRefPtr<MediaMgrError>( |
3426 | MediaMgrError::Name::NotAllowedError, |
3427 | "Document's Permissions Policy does not allow selectAudioOutput()"), |
3428 | __func__); |
3429 | } |
3430 | if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3430)) { |
3431 | return LocalDevicePromise::CreateAndReject( |
3432 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
3433 | __func__); |
3434 | } |
3435 | // Disallow access to null principal. |
3436 | if (principal->GetIsNullPrincipal()) { |
3437 | return LocalDevicePromise::CreateAndReject( |
3438 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
3439 | __func__); |
3440 | } |
3441 | ipc::PrincipalInfo principalInfo; |
3442 | nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo); |
3443 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3443)) { |
3444 | return LocalDevicePromise::CreateAndReject( |
3445 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
3446 | __func__); |
3447 | } |
3448 | uint64_t windowID = aWindow->WindowID(); |
3449 | const bool resistFingerprinting = |
3450 | aWindow->AsGlobal()->ShouldResistFingerprinting(aCallerType, |
3451 | RFPTarget::MediaDevices); |
3452 | return EnumerateDevicesImpl( |
3453 | aWindow, CreateEnumerationParams( |
3454 | MediaSourceEnum::Other, MediaSourceEnum::Other, |
3455 | {EnumerationFlag::EnumerateAudioOutputs, |
3456 | EnumerationFlag::AllowPermissionRequest})) |
3457 | ->Then( |
3458 | GetCurrentSerialEventTarget(), __func__, |
3459 | [self = RefPtr<MediaManager>(this), windowID, aOptions, aCallerType, |
3460 | resistFingerprinting, isHandlingUserInput, |
3461 | principalInfo](RefPtr<LocalMediaDeviceSetRefCnt> aDevices) mutable { |
3462 | // Ensure that the window is still good. |
3463 | RefPtr<nsPIDOMWindowInner> window = |
3464 | nsGlobalWindowInner::GetInnerWindowWithId(windowID); |
3465 | if (!window) { |
3466 | LOG("SelectAudioOutput: bad window (%" PRIu64"l" "u" |
3467 | ") in post enumeration success callback!", |
3468 | windowID); |
3469 | return LocalDevicePromise::CreateAndReject( |
3470 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3471 | __func__); |
3472 | } |
3473 | if (aDevices->IsEmpty()) { |
3474 | LOG("SelectAudioOutput: no devices found"); |
3475 | auto error = resistFingerprinting |
3476 | ? MediaMgrError::Name::NotAllowedError |
3477 | : MediaMgrError::Name::NotFoundError; |
3478 | return LocalDevicePromise::CreateAndReject( |
3479 | MakeRefPtr<MediaMgrError>(error), __func__); |
3480 | } |
3481 | MozPromiseHolder<LocalDevicePromise> holder; |
3482 | RefPtr<LocalDevicePromise> p = holder.Ensure(__func__); |
3483 | auto task = MakeRefPtr<SelectAudioOutputTask>( |
3484 | std::move(holder), windowID, aCallerType, principalInfo); |
3485 | nsString callID; |
3486 | nsresult rv = GenerateUUID(callID); |
3487 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3487); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3487; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3488 | size_t taskCount = |
3489 | self->AddTaskAndGetCount(windowID, callID, std::move(task)); |
3490 | bool askPermission = |
3491 | !Preferences::GetBool("media.navigator.permission.disabled") || |
3492 | Preferences::GetBool("media.navigator.permission.force"); |
3493 | if (!askPermission) { |
3494 | self->NotifyAllowed(callID, *aDevices); |
3495 | } else { |
3496 | MOZ_ASSERT(window->IsSecureContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(window->IsSecureContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(window->IsSecureContext() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "window->IsSecureContext()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3496); AnnotateMozCrashReason("MOZ_ASSERT" "(" "window->IsSecureContext()" ")"); do { *((volatile int*)__null) = 3496; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3497 | auto req = MakeRefPtr<GetUserMediaRequest>( |
3498 | window, callID, std::move(aDevices), aOptions, true, |
3499 | isHandlingUserInput); |
3500 | if (taskCount > 1) { |
3501 | // there is at least 1 pending gUM request |
3502 | self->mPendingGUMRequest.AppendElement(req.forget()); |
3503 | } else { |
3504 | nsCOMPtr<nsIObserverService> obs = |
3505 | services::GetObserverService(); |
3506 | obs->NotifyObservers(req, "getUserMedia:request", nullptr); |
3507 | } |
3508 | } |
3509 | return p; |
3510 | }, |
3511 | [](RefPtr<MediaMgrError> aError) { |
3512 | LOG("SelectAudioOutput: EnumerateDevicesImpl " |
3513 | "failure callback called!"); |
3514 | return LocalDevicePromise::CreateAndReject(std::move(aError), |
3515 | __func__); |
3516 | }); |
3517 | } |
3518 | |
3519 | MediaEngine* MediaManager::GetBackend() { |
3520 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3520; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3521 | // Plugin backends as appropriate. The default engine also currently |
3522 | // includes picture support for Android. |
3523 | // This IS called off main-thread. |
3524 | if (!mBackend) { |
3525 | #if defined(MOZ_WEBRTC1) |
3526 | mBackend = new MediaEngineWebRTC(); |
3527 | #else |
3528 | mBackend = new MediaEngineFake(); |
3529 | #endif |
3530 | mDeviceListChangeListener = mBackend->DeviceListChangeEvent().Connect( |
3531 | AbstractThread::MainThread(), this, &MediaManager::DeviceListChanged); |
3532 | } |
3533 | return mBackend; |
3534 | } |
3535 | |
3536 | void MediaManager::OnNavigation(uint64_t aWindowID) { |
3537 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3537; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3538 | LOG("OnNavigation for %" PRIu64"l" "u", aWindowID); |
3539 | |
3540 | // Stop the streams for this window. The runnables check this value before |
3541 | // making a call to content. |
3542 | |
3543 | nsTArray<nsString>* callIDs; |
3544 | if (mCallIds.Get(aWindowID, &callIDs)) { |
3545 | for (auto& callID : *callIDs) { |
3546 | mActiveCallbacks.Remove(callID); |
3547 | for (auto& request : mPendingGUMRequest.Clone()) { |
3548 | nsString id; |
3549 | request->GetCallID(id); |
3550 | if (id == callID) { |
3551 | mPendingGUMRequest.RemoveElement(request); |
3552 | } |
3553 | } |
3554 | } |
3555 | mCallIds.Remove(aWindowID); |
3556 | } |
3557 | |
3558 | if (RefPtr<GetUserMediaWindowListener> listener = |
3559 | GetWindowListener(aWindowID)) { |
3560 | listener->RemoveAll(); |
3561 | } |
3562 | MOZ_ASSERT(!GetWindowListener(aWindowID))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!GetWindowListener(aWindowID))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!GetWindowListener(aWindowID )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!GetWindowListener(aWindowID)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowListener(aWindowID)" ")"); do { *((volatile int*)__null) = 3562; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3563 | } |
3564 | |
3565 | void MediaManager::OnCameraMute(bool aMute) { |
3566 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3566); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3566; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3567 | LOG("OnCameraMute for all windows"); |
3568 | mCamerasMuted = aMute; |
3569 | // This is safe since we're on main-thread, and the windowlist can only |
3570 | // be added to from the main-thread |
3571 | for (const auto& window : mActiveWindows.Values()) { |
3572 | window->MuteOrUnmuteCameras(aMute); |
3573 | } |
3574 | } |
3575 | |
3576 | void MediaManager::OnMicrophoneMute(bool aMute) { |
3577 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3577; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3578 | LOG("OnMicrophoneMute for all windows"); |
3579 | mMicrophonesMuted = aMute; |
3580 | // This is safe since we're on main-thread, and the windowlist can only |
3581 | // be added to from the main-thread |
3582 | for (const auto& window : mActiveWindows.Values()) { |
3583 | window->MuteOrUnmuteMicrophones(aMute); |
3584 | } |
3585 | } |
3586 | |
3587 | RefPtr<GetUserMediaWindowListener> MediaManager::GetOrMakeWindowListener( |
3588 | nsPIDOMWindowInner* aWindow) { |
3589 | Document* doc = aWindow->GetExtantDoc(); |
3590 | if (!doc) { |
3591 | // The window has been destroyed. Destroyed windows don't have listeners. |
3592 | return nullptr; |
3593 | } |
3594 | nsIPrincipal* principal = doc->NodePrincipal(); |
3595 | uint64_t windowId = aWindow->WindowID(); |
3596 | RefPtr<GetUserMediaWindowListener> windowListener = |
3597 | GetWindowListener(windowId); |
3598 | if (windowListener) { |
3599 | MOZ_ASSERT(PrincipalHandleMatches(windowListener->GetPrincipalHandle(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(PrincipalHandleMatches(windowListener->GetPrincipalHandle (), principal))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(PrincipalHandleMatches(windowListener ->GetPrincipalHandle(), principal)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3600); AnnotateMozCrashReason("MOZ_ASSERT" "(" "PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)" ")"); do { *((volatile int*)__null) = 3600; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
3600 | principal))do { static_assert( mozilla::detail::AssertionConditionType< decltype(PrincipalHandleMatches(windowListener->GetPrincipalHandle (), principal))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(PrincipalHandleMatches(windowListener ->GetPrincipalHandle(), principal)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3600); AnnotateMozCrashReason("MOZ_ASSERT" "(" "PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)" ")"); do { *((volatile int*)__null) = 3600; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3601 | } else { |
3602 | windowListener = new GetUserMediaWindowListener( |
3603 | windowId, MakePrincipalHandle(principal)); |
3604 | AddWindowID(windowId, windowListener); |
3605 | } |
3606 | return windowListener; |
3607 | } |
3608 | |
3609 | void MediaManager::AddWindowID(uint64_t aWindowId, |
3610 | RefPtr<GetUserMediaWindowListener> aListener) { |
3611 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3611; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3612 | // Store the WindowID in a hash table and mark as active. The entry is removed |
3613 | // when this window is closed or navigated away from. |
3614 | // This is safe since we're on main-thread, and the windowlist can only |
3615 | // be invalidated from the main-thread (see OnNavigation) |
3616 | if (IsWindowStillActive(aWindowId)) { |
3617 | MOZ_ASSERT(false, "Window already added")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "Window already added" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Window already added" ")"); do { *((volatile int*)__null) = 3617; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3618 | return; |
3619 | } |
3620 | |
3621 | aListener->MuteOrUnmuteCameras(mCamerasMuted); |
3622 | aListener->MuteOrUnmuteMicrophones(mMicrophonesMuted); |
3623 | GetActiveWindows()->InsertOrUpdate(aWindowId, std::move(aListener)); |
3624 | |
3625 | RefPtr<WindowGlobalChild> wgc = |
3626 | WindowGlobalChild::GetByInnerWindowId(aWindowId); |
3627 | if (wgc) { |
3628 | wgc->BlockBFCacheFor(BFCacheStatus::ACTIVE_GET_USER_MEDIA); |
3629 | } |
3630 | } |
3631 | |
3632 | void MediaManager::RemoveWindowID(uint64_t aWindowId) { |
3633 | RefPtr<WindowGlobalChild> wgc = |
3634 | WindowGlobalChild::GetByInnerWindowId(aWindowId); |
3635 | if (wgc) { |
3636 | wgc->UnblockBFCacheFor(BFCacheStatus::ACTIVE_GET_USER_MEDIA); |
3637 | } |
3638 | |
3639 | mActiveWindows.Remove(aWindowId); |
3640 | |
3641 | // get outer windowID |
3642 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowId); |
3643 | if (!window) { |
3644 | LOG("No inner window for %" PRIu64"l" "u", aWindowId); |
3645 | return; |
3646 | } |
3647 | |
3648 | auto* outer = window->GetOuterWindow(); |
3649 | if (!outer) { |
3650 | LOG("No outer window for inner %" PRIu64"l" "u", aWindowId); |
3651 | return; |
3652 | } |
3653 | |
3654 | uint64_t outerID = outer->WindowID(); |
3655 | |
3656 | // Notify the UI that this window no longer has gUM active |
3657 | char windowBuffer[32]; |
3658 | SprintfLiteral(windowBuffer, "%" PRIu64"l" "u", outerID); |
3659 | nsString data = NS_ConvertUTF8toUTF16(windowBuffer); |
3660 | |
3661 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
3662 | obs->NotifyWhenScriptSafe(nullptr, "recording-window-ended", data.get()); |
3663 | LOG("Sent recording-window-ended for window %" PRIu64"l" "u" " (outer %" PRIu64"l" "u" ")", |
3664 | aWindowId, outerID); |
3665 | } |
3666 | |
3667 | bool MediaManager::IsWindowListenerStillActive( |
3668 | const RefPtr<GetUserMediaWindowListener>& aListener) { |
3669 | MOZ_DIAGNOSTIC_ASSERT(aListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aListener", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3669); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aListener" ")"); do { *((volatile int*)__null) = 3669; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3670 | return aListener && aListener == GetWindowListener(aListener->WindowID()); |
3671 | } |
3672 | |
3673 | void MediaManager::GetPref(nsIPrefBranch* aBranch, const char* aPref, |
3674 | const char* aData, int32_t* aVal) { |
3675 | int32_t temp; |
3676 | if (aData == nullptr || strcmp(aPref, aData) == 0) { |
3677 | if (NS_SUCCEEDED(aBranch->GetIntPref(aPref, &temp))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aBranch->GetIntPref (aPref, &temp))), 1)))) { |
3678 | *aVal = temp; |
3679 | } |
3680 | } |
3681 | } |
3682 | |
3683 | void MediaManager::GetPrefBool(nsIPrefBranch* aBranch, const char* aPref, |
3684 | const char* aData, bool* aVal) { |
3685 | bool temp; |
3686 | if (aData == nullptr || strcmp(aPref, aData) == 0) { |
3687 | if (NS_SUCCEEDED(aBranch->GetBoolPref(aPref, &temp))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aBranch->GetBoolPref (aPref, &temp))), 1)))) { |
3688 | *aVal = temp; |
3689 | } |
3690 | } |
3691 | } |
3692 | |
3693 | void MediaManager::GetPrefs(nsIPrefBranch* aBranch, const char* aData) { |
3694 | GetPref(aBranch, "media.navigator.video.default_width", aData, |
3695 | &mPrefs.mWidth); |
3696 | GetPref(aBranch, "media.navigator.video.default_height", aData, |
3697 | &mPrefs.mHeight); |
3698 | GetPref(aBranch, "media.navigator.video.default_fps", aData, &mPrefs.mFPS); |
3699 | GetPref(aBranch, "media.navigator.audio.fake_frequency", aData, |
3700 | &mPrefs.mFreq); |
3701 | #ifdef MOZ_WEBRTC1 |
3702 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.platform.enabled", |
3703 | aData, &mPrefs.mUsePlatformProcessing); |
3704 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.aec.enabled", aData, |
3705 | &mPrefs.mAecOn); |
3706 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.agc.enabled", aData, |
3707 | &mPrefs.mAgcOn); |
3708 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.hpf.enabled", aData, |
3709 | &mPrefs.mHPFOn); |
3710 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.noise.enabled", |
3711 | aData, &mPrefs.mNoiseOn); |
3712 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.transient.enabled", |
3713 | aData, &mPrefs.mTransientOn); |
3714 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.agc2.forced", aData, |
3715 | &mPrefs.mAgc2Forced); |
3716 | // Use 0 or 1 to force to false or true |
3717 | // EchoCanceller3Config::echo_removal_control.has_clock_drift. |
3718 | // -1 is the default, which means automatically set has_clock_drift as |
3719 | // deemed appropriate. |
3720 | GetPref(aBranch, "media.getusermedia.audio.processing.aec.expect_drift", |
3721 | aData, &mPrefs.mExpectDrift); |
3722 | GetPref(aBranch, "media.getusermedia.audio.processing.agc", aData, |
3723 | &mPrefs.mAgc); |
3724 | GetPref(aBranch, "media.getusermedia.audio.processing.noise", aData, |
3725 | &mPrefs.mNoise); |
3726 | GetPref(aBranch, "media.getusermedia.audio.max_channels", aData, |
3727 | &mPrefs.mChannels); |
3728 | #endif |
3729 | LOG("%s: default prefs: %dx%d @%dfps, %dHz test tones, platform processing: " |
3730 | "%s, aec: %s, agc: %s, hpf: %s, noise: %s, drift: %s, agc level: %d, agc " |
3731 | "version: " |
3732 | "%s, noise level: %d, transient: %s, channels %d", |
3733 | __FUNCTION__, mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mFreq, |
3734 | mPrefs.mUsePlatformProcessing ? "on" : "off", |
3735 | mPrefs.mAecOn ? "on" : "off", mPrefs.mAgcOn ? "on" : "off", |
3736 | mPrefs.mHPFOn ? "on" : "off", mPrefs.mNoiseOn ? "on" : "off", |
3737 | mPrefs.mExpectDrift < 0 ? "auto" |
3738 | : mPrefs.mExpectDrift ? "on" |
3739 | : "off", |
3740 | mPrefs.mAgc, mPrefs.mAgc2Forced ? "2" : "1", mPrefs.mNoise, |
3741 | mPrefs.mTransientOn ? "on" : "off", mPrefs.mChannels); |
3742 | } |
3743 | |
3744 | void MediaManager::Shutdown() { |
3745 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3745; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3746 | if (sHasMainThreadShutdown) { |
3747 | return; |
3748 | } |
3749 | |
3750 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
3751 | |
3752 | obs->RemoveObserver(this, "last-pb-context-exited"); |
3753 | obs->RemoveObserver(this, "getUserMedia:privileged:allow"); |
3754 | obs->RemoveObserver(this, "getUserMedia:response:allow"); |
3755 | obs->RemoveObserver(this, "getUserMedia:response:deny"); |
3756 | obs->RemoveObserver(this, "getUserMedia:response:noOSPermission"); |
3757 | obs->RemoveObserver(this, "getUserMedia:revoke"); |
3758 | obs->RemoveObserver(this, "getUserMedia:muteVideo"); |
3759 | obs->RemoveObserver(this, "getUserMedia:unmuteVideo"); |
3760 | obs->RemoveObserver(this, "getUserMedia:muteAudio"); |
3761 | obs->RemoveObserver(this, "getUserMedia:unmuteAudio"); |
3762 | obs->RemoveObserver(this, "application-background"); |
3763 | obs->RemoveObserver(this, "application-foreground"); |
3764 | |
3765 | nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1"); |
3766 | if (prefs) { |
3767 | ForeachObservedPref([&](const nsLiteralCString& aPrefName) { |
3768 | prefs->RemoveObserver(aPrefName, this); |
3769 | }); |
3770 | } |
3771 | |
3772 | if (mDeviceChangeTimer) { |
3773 | mDeviceChangeTimer->Cancel(); |
3774 | // Drop ref to MediaTimer early to avoid blocking SharedThreadPool shutdown |
3775 | mDeviceChangeTimer = nullptr; |
3776 | } |
3777 | |
3778 | { |
3779 | // Close off any remaining active windows. |
3780 | |
3781 | // Live capture at this point is rare but can happen. Stopping it will make |
3782 | // the window listeners attempt to remove themselves from the active windows |
3783 | // table. We cannot touch the table at point so we grab a copy of the window |
3784 | // listeners first. |
3785 | const auto listeners = ToArray(GetActiveWindows()->Values()); |
3786 | for (const auto& listener : listeners) { |
3787 | listener->RemoveAll(); |
3788 | } |
3789 | } |
3790 | MOZ_ASSERT(GetActiveWindows()->Count() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetActiveWindows()->Count() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetActiveWindows()->Count () == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetActiveWindows()->Count() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetActiveWindows()->Count() == 0" ")"); do { *((volatile int*)__null) = 3790; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3791 | |
3792 | GetActiveWindows()->Clear(); |
3793 | mActiveCallbacks.Clear(); |
3794 | mCallIds.Clear(); |
3795 | mPendingGUMRequest.Clear(); |
3796 | #ifdef MOZ_WEBRTC1 |
3797 | mLogHandle = nullptr; |
3798 | #endif |
3799 | |
3800 | // From main thread's point of view, shutdown is now done. |
3801 | // All that remains is shutting down the media thread. |
3802 | sHasMainThreadShutdown = true; |
3803 | |
3804 | // Release the backend (and call Shutdown()) from within mMediaThread. |
3805 | // Don't use MediaManager::Dispatch() because we're |
3806 | // sHasMainThreadShutdown == true here! |
3807 | MOZ_ALWAYS_SUCCEEDS(mMediaThread->Dispatch(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3808 | NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3809 | LOG("MediaManager Thread Shutdown");do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3810 | MOZ_ASSERT(IsInMediaThread());do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3811 | // Must shutdown backend on MediaManager thread, since that'sdo { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3812 | // where we started it from!do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3813 | if (mBackend) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3814 | mBackend->Shutdown(); // idempotentdo { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3815 | mDeviceListChangeListener.DisconnectIfExists();do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3816 | }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3817 | // last reference, will invoke Shutdown() againdo { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3818 | mBackend = nullptr;do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ) |
3819 | })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3819); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3810); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3810; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3819; __attribute__((nomerge )) ::abort(); } while (false); } while (false); } } while (false ); |
3820 | |
3821 | // note that this == sSingleton |
3822 | MOZ_ASSERT(this == sSingleton)do { static_assert( mozilla::detail::AssertionConditionType< decltype(this == sSingleton)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(this == sSingleton))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("this == sSingleton" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3822); AnnotateMozCrashReason("MOZ_ASSERT" "(" "this == sSingleton" ")"); do { *((volatile int*)__null) = 3822; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3823 | |
3824 | // Explicitly shut down the TaskQueue so that it releases its |
3825 | // SharedThreadPool when all tasks have completed. SharedThreadPool blocks |
3826 | // XPCOM shutdown from proceeding beyond "xpcom-shutdown-threads" until all |
3827 | // SharedThreadPools are released, but the nsComponentManager keeps a |
3828 | // reference to the MediaManager for the nsIMediaManagerService until much |
3829 | // later in shutdown. This also provides additional assurance that no |
3830 | // further tasks will be queued. |
3831 | mMediaThread->BeginShutdown()->Then( |
3832 | GetMainThreadSerialEventTarget(), __func__, [] { |
3833 | LOG("MediaManager shutdown lambda running, releasing MediaManager " |
3834 | "singleton"); |
3835 | // Remove async shutdown blocker |
3836 | media::MustGetShutdownBarrier()->RemoveBlocker( |
3837 | sSingleton->mShutdownBlocker); |
3838 | |
3839 | sSingleton = nullptr; |
3840 | }); |
3841 | } |
3842 | |
3843 | void MediaManager::SendPendingGUMRequest() { |
3844 | if (mPendingGUMRequest.Length() > 0) { |
3845 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
3846 | obs->NotifyObservers(mPendingGUMRequest[0], "getUserMedia:request", |
3847 | nullptr); |
3848 | mPendingGUMRequest.RemoveElementAt(0); |
3849 | } |
3850 | } |
3851 | |
3852 | bool IsGUMResponseNoAccess(const char* aTopic, |
3853 | MediaMgrError::Name& aErrorName) { |
3854 | if (!strcmp(aTopic, "getUserMedia:response:deny")) { |
3855 | aErrorName = MediaMgrError::Name::NotAllowedError; |
3856 | return true; |
3857 | } |
3858 | |
3859 | if (!strcmp(aTopic, "getUserMedia:response:noOSPermission")) { |
3860 | aErrorName = MediaMgrError::Name::NotFoundError; |
3861 | return true; |
3862 | } |
3863 | |
3864 | return false; |
3865 | } |
3866 | |
3867 | static MediaSourceEnum ParseScreenColonWindowID(const char16_t* aData, |
3868 | uint64_t* aWindowIDOut) { |
3869 | MOZ_ASSERT(aWindowIDOut)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWindowIDOut)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWindowIDOut))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWindowIDOut", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3869); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowIDOut" ")"); do { *((volatile int*)__null) = 3869; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3870 | // may be windowid or screen:windowid |
3871 | const nsDependentString data(aData); |
3872 | if (Substring(data, 0, strlen("screen:")).EqualsLiteral("screen:")) { |
3873 | nsresult rv; |
3874 | *aWindowIDOut = Substring(data, strlen("screen:")).ToInteger64(&rv); |
3875 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3875); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3875; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3876 | return MediaSourceEnum::Screen; |
3877 | } |
3878 | nsresult rv; |
3879 | *aWindowIDOut = data.ToInteger64(&rv); |
3880 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3880); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3880; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3881 | return MediaSourceEnum::Camera; |
3882 | } |
3883 | |
3884 | nsresult MediaManager::Observe(nsISupports* aSubject, const char* aTopic, |
3885 | const char16_t* aData) { |
3886 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3886; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3887 | |
3888 | MediaMgrError::Name gumNoAccessError = MediaMgrError::Name::NotAllowedError; |
3889 | |
3890 | if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID"nsPref:changed")) { |
3891 | nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(aSubject)); |
3892 | if (branch) { |
3893 | GetPrefs(branch, NS_ConvertUTF16toUTF8(aData).get()); |
3894 | DeviceListChanged(); |
3895 | } |
3896 | } else if (!strcmp(aTopic, "last-pb-context-exited")) { |
3897 | // Clear memory of private-browsing-specific deviceIds. Fire and forget. |
3898 | media::SanitizeOriginKeys(0, true); |
3899 | return NS_OK; |
3900 | } else if (!strcmp(aTopic, "getUserMedia:got-device-permission")) { |
3901 | MOZ_ASSERT(aSubject)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSubject)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aSubject))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSubject", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3901); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSubject" ")" ); do { *((volatile int*)__null) = 3901; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3902 | nsCOMPtr<nsIRunnable> task = do_QueryInterface(aSubject); |
3903 | MediaManager::Dispatch(NewTaskFrom([task] { task->Run(); })); |
3904 | return NS_OK; |
3905 | } else if (!strcmp(aTopic, "getUserMedia:privileged:allow") || |
3906 | !strcmp(aTopic, "getUserMedia:response:allow")) { |
3907 | nsString key(aData); |
3908 | RefPtr<GetUserMediaTask> task = TakeGetUserMediaTask(key); |
3909 | if (!task) { |
3910 | return NS_OK; |
3911 | } |
3912 | |
3913 | if (sHasMainThreadShutdown) { |
3914 | task->Denied(MediaMgrError::Name::AbortError, "In shutdown"_ns); |
3915 | return NS_OK; |
3916 | } |
3917 | if (NS_WARN_IF(!aSubject)NS_warn_if_impl(!aSubject, "!aSubject", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3917)) { |
3918 | return NS_ERROR_FAILURE; // ignored |
3919 | } |
3920 | // Permission has been granted. aSubject contains the particular device |
3921 | // or devices selected and approved by the user, if any. |
3922 | nsCOMPtr<nsIArray> array(do_QueryInterface(aSubject)); |
3923 | MOZ_ASSERT(array)do { static_assert( mozilla::detail::AssertionConditionType< decltype(array)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(array))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("array", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "array" ")") ; do { *((volatile int*)__null) = 3923; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3924 | uint32_t len = 0; |
3925 | array->GetLength(&len); |
3926 | RefPtr<LocalMediaDevice> audioInput; |
3927 | RefPtr<LocalMediaDevice> videoInput; |
3928 | RefPtr<LocalMediaDevice> audioOutput; |
3929 | for (uint32_t i = 0; i < len; i++) { |
3930 | nsCOMPtr<nsIMediaDevice> device; |
3931 | array->QueryElementAt(i, NS_GET_IID(nsIMediaDevice)(nsIMediaDevice::COMTypeInfo<nsIMediaDevice, void>::kIID ), |
3932 | getter_AddRefs(device)); |
3933 | MOZ_ASSERT(device)do { static_assert( mozilla::detail::AssertionConditionType< decltype(device)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(device))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("device", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "device" ")" ); do { *((volatile int*)__null) = 3933; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); // shouldn't be returning anything else... |
3934 | if (!device) { |
3935 | continue; |
3936 | } |
3937 | |
3938 | // Casting here is safe because a LocalMediaDevice is created |
3939 | // only in Gecko side, JS can only query for an instance. |
3940 | auto* dev = static_cast<LocalMediaDevice*>(device.get()); |
3941 | switch (dev->Kind()) { |
3942 | case MediaDeviceKind::Videoinput: |
3943 | if (!videoInput) { |
3944 | videoInput = dev; |
3945 | } |
3946 | break; |
3947 | case MediaDeviceKind::Audioinput: |
3948 | if (!audioInput) { |
3949 | audioInput = dev; |
3950 | } |
3951 | break; |
3952 | case MediaDeviceKind::Audiooutput: |
3953 | if (!audioOutput) { |
3954 | audioOutput = dev; |
3955 | } |
3956 | break; |
3957 | default: |
3958 | MOZ_CRASH("Unexpected device kind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected device kind" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3958); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected device kind" ")"); do { *((volatile int*)__null) = 3958; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
3959 | } |
3960 | } |
3961 | |
3962 | if (GetUserMediaStreamTask* streamTask = task->AsGetUserMediaStreamTask()) { |
3963 | bool needVideo = IsOn(streamTask->GetConstraints().mVideo); |
3964 | bool needAudio = IsOn(streamTask->GetConstraints().mAudio); |
3965 | MOZ_ASSERT(needVideo || needAudio)do { static_assert( mozilla::detail::AssertionConditionType< decltype(needVideo || needAudio)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(needVideo || needAudio))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("needVideo || needAudio" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3965); AnnotateMozCrashReason("MOZ_ASSERT" "(" "needVideo || needAudio" ")"); do { *((volatile int*)__null) = 3965; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3966 | |
3967 | if ((needVideo && !videoInput) || (needAudio && !audioInput)) { |
3968 | task->Denied(MediaMgrError::Name::NotAllowedError); |
3969 | return NS_OK; |
3970 | } |
3971 | streamTask->Allowed(std::move(audioInput), std::move(videoInput)); |
3972 | return NS_OK; |
3973 | } |
3974 | if (SelectAudioOutputTask* outputTask = task->AsSelectAudioOutputTask()) { |
3975 | if (!audioOutput) { |
3976 | task->Denied(MediaMgrError::Name::NotAllowedError); |
3977 | return NS_OK; |
3978 | } |
3979 | outputTask->Allowed(std::move(audioOutput)); |
3980 | return NS_OK; |
3981 | } |
3982 | |
3983 | NS_WARNING("Unknown task type in getUserMedia")NS_DebugBreak(NS_DEBUG_WARNING, "Unknown task type in getUserMedia" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3983); |
3984 | return NS_ERROR_FAILURE; |
3985 | |
3986 | } else if (IsGUMResponseNoAccess(aTopic, gumNoAccessError)) { |
3987 | nsString key(aData); |
3988 | RefPtr<GetUserMediaTask> task = TakeGetUserMediaTask(key); |
3989 | if (task) { |
3990 | task->Denied(gumNoAccessError); |
3991 | SendPendingGUMRequest(); |
3992 | } |
3993 | return NS_OK; |
3994 | |
3995 | } else if (!strcmp(aTopic, "getUserMedia:revoke")) { |
3996 | uint64_t windowID; |
3997 | if (ParseScreenColonWindowID(aData, &windowID) == MediaSourceEnum::Screen) { |
3998 | LOG("Revoking ScreenCapture access for window %" PRIu64"l" "u", windowID); |
3999 | StopScreensharing(windowID); |
4000 | } else { |
4001 | LOG("Revoking MediaCapture access for window %" PRIu64"l" "u", windowID); |
4002 | OnNavigation(windowID); |
4003 | } |
4004 | return NS_OK; |
4005 | } else if (!strcmp(aTopic, "getUserMedia:muteVideo") || |
4006 | !strcmp(aTopic, "getUserMedia:unmuteVideo")) { |
4007 | OnCameraMute(!strcmp(aTopic, "getUserMedia:muteVideo")); |
4008 | return NS_OK; |
4009 | } else if (!strcmp(aTopic, "getUserMedia:muteAudio") || |
4010 | !strcmp(aTopic, "getUserMedia:unmuteAudio")) { |
4011 | OnMicrophoneMute(!strcmp(aTopic, "getUserMedia:muteAudio")); |
4012 | return NS_OK; |
4013 | } else if ((!strcmp(aTopic, "application-background") || |
4014 | !strcmp(aTopic, "application-foreground")) && |
4015 | StaticPrefs::media_getusermedia_camera_background_mute_enabled()) { |
4016 | // On mobile we turn off any cameras (but not mics) while in the background. |
4017 | // Keeping things simple for now by duplicating test-covered code above. |
4018 | // |
4019 | // NOTE: If a mobile device ever wants to implement "getUserMedia:muteVideo" |
4020 | // as well, it'd need to update this code to handle & test the combinations. |
4021 | OnCameraMute(!strcmp(aTopic, "application-background")); |
4022 | } |
4023 | |
4024 | return NS_OK; |
4025 | } |
4026 | |
4027 | NS_IMETHODIMPnsresult |
4028 | MediaManager::CollectReports(nsIHandleReportCallback* aHandleReport, |
4029 | nsISupports* aData, bool aAnonymize) { |
4030 | size_t amount = 0; |
4031 | amount += mActiveWindows.ShallowSizeOfExcludingThis(MallocSizeOf); |
4032 | for (const GetUserMediaWindowListener* listener : mActiveWindows.Values()) { |
4033 | amount += listener->SizeOfIncludingThis(MallocSizeOf); |
4034 | } |
4035 | amount += mActiveCallbacks.ShallowSizeOfExcludingThis(MallocSizeOf); |
4036 | for (const GetUserMediaTask* task : mActiveCallbacks.Values()) { |
4037 | // Assume nsString buffers for keys are accounted in mCallIds. |
4038 | amount += task->SizeOfIncludingThis(MallocSizeOf); |
4039 | } |
4040 | amount += mCallIds.ShallowSizeOfExcludingThis(MallocSizeOf); |
4041 | for (const auto& array : mCallIds.Values()) { |
4042 | amount += array->ShallowSizeOfExcludingThis(MallocSizeOf); |
4043 | for (const nsString& callID : *array) { |
4044 | amount += callID.SizeOfExcludingThisEvenIfShared(MallocSizeOf); |
4045 | } |
4046 | } |
4047 | amount += mPendingGUMRequest.ShallowSizeOfExcludingThis(MallocSizeOf); |
4048 | // GetUserMediaRequest pointees of mPendingGUMRequest do not have support |
4049 | // for memory accounting. mPendingGUMRequest logic should probably be moved |
4050 | // to the front end (bug 1691625). |
4051 | MOZ_COLLECT_REPORT("explicit/media/media-manager-aggregates", KIND_HEAP,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/media/media-manager-aggregates" ), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by MediaManager variable length members." ), aData) |
4052 | UNITS_BYTES, amount,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/media/media-manager-aggregates" ), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by MediaManager variable length members." ), aData) |
4053 | "Memory used by MediaManager variable length members.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/media/media-manager-aggregates" ), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by MediaManager variable length members." ), aData); |
4054 | return NS_OK; |
4055 | } |
4056 | |
4057 | nsresult MediaManager::GetActiveMediaCaptureWindows(nsIArray** aArray) { |
4058 | MOZ_ASSERT(aArray)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aArray)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aArray))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aArray", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aArray" ")" ); do { *((volatile int*)__null) = 4058; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4059 | |
4060 | nsCOMPtr<nsIMutableArray> array = nsArray::Create(); |
4061 | |
4062 | for (const auto& entry : mActiveWindows) { |
4063 | const uint64_t& id = entry.GetKey(); |
4064 | RefPtr<GetUserMediaWindowListener> winListener = entry.GetData(); |
4065 | if (!winListener) { |
4066 | continue; |
4067 | } |
4068 | |
4069 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(id); |
4070 | MOZ_ASSERT(window)do { static_assert( mozilla::detail::AssertionConditionType< decltype(window)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(window))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("window", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4070); AnnotateMozCrashReason("MOZ_ASSERT" "(" "window" ")" ); do { *((volatile int*)__null) = 4070; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4071 | // XXXkhuey ... |
4072 | if (!window) { |
4073 | continue; |
4074 | } |
4075 | |
4076 | if (winListener->CapturingVideo() || winListener->CapturingAudio()) { |
4077 | array->AppendElement(ToSupports(window)); |
4078 | } |
4079 | } |
4080 | |
4081 | array.forget(aArray); |
4082 | return NS_OK; |
4083 | } |
4084 | |
4085 | struct CaptureWindowStateData { |
4086 | uint16_t* mCamera; |
4087 | uint16_t* mMicrophone; |
4088 | uint16_t* mScreenShare; |
4089 | uint16_t* mWindowShare; |
4090 | uint16_t* mAppShare; |
4091 | uint16_t* mBrowserShare; |
4092 | }; |
4093 | |
4094 | NS_IMETHODIMPnsresult |
4095 | MediaManager::MediaCaptureWindowState( |
4096 | nsIDOMWindow* aCapturedWindow, uint16_t* aCamera, uint16_t* aMicrophone, |
4097 | uint16_t* aScreen, uint16_t* aWindow, uint16_t* aBrowser, |
4098 | nsTArray<RefPtr<nsIMediaDevice>>& aDevices) { |
4099 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4099); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4099; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4100 | |
4101 | CaptureState camera = CaptureState::Off; |
4102 | CaptureState microphone = CaptureState::Off; |
4103 | CaptureState screen = CaptureState::Off; |
4104 | CaptureState window = CaptureState::Off; |
4105 | CaptureState browser = CaptureState::Off; |
4106 | RefPtr<LocalMediaDeviceSetRefCnt> devices; |
4107 | |
4108 | nsCOMPtr<nsPIDOMWindowInner> piWin = do_QueryInterface(aCapturedWindow); |
4109 | if (piWin) { |
4110 | if (RefPtr<GetUserMediaWindowListener> listener = |
4111 | GetWindowListener(piWin->WindowID())) { |
4112 | camera = listener->CapturingSource(MediaSourceEnum::Camera); |
4113 | microphone = listener->CapturingSource(MediaSourceEnum::Microphone); |
4114 | screen = listener->CapturingSource(MediaSourceEnum::Screen); |
4115 | window = listener->CapturingSource(MediaSourceEnum::Window); |
4116 | browser = listener->CapturingSource(MediaSourceEnum::Browser); |
4117 | devices = listener->GetDevices(); |
4118 | } |
4119 | } |
4120 | |
4121 | *aCamera = FromCaptureState(camera); |
4122 | *aMicrophone = FromCaptureState(microphone); |
4123 | *aScreen = FromCaptureState(screen); |
4124 | *aWindow = FromCaptureState(window); |
4125 | *aBrowser = FromCaptureState(browser); |
4126 | if (devices) { |
4127 | for (auto& device : *devices) { |
4128 | aDevices.AppendElement(device); |
4129 | } |
4130 | } |
4131 | |
4132 | LOG("%s: window %" PRIu64"l" "u" " capturing %s %s %s %s %s", __FUNCTION__, |
4133 | piWin ? piWin->WindowID() : -1, |
4134 | *aCamera == nsIMediaManagerService::STATE_CAPTURE_ENABLED |
4135 | ? "camera (enabled)" |
4136 | : (*aCamera == nsIMediaManagerService::STATE_CAPTURE_DISABLED |
4137 | ? "camera (disabled)" |
4138 | : ""), |
4139 | *aMicrophone == nsIMediaManagerService::STATE_CAPTURE_ENABLED |
4140 | ? "microphone (enabled)" |
4141 | : (*aMicrophone == nsIMediaManagerService::STATE_CAPTURE_DISABLED |
4142 | ? "microphone (disabled)" |
4143 | : ""), |
4144 | *aScreen ? "screenshare" : "", *aWindow ? "windowshare" : "", |
4145 | *aBrowser ? "browsershare" : ""); |
4146 | |
4147 | return NS_OK; |
4148 | } |
4149 | |
4150 | NS_IMETHODIMPnsresult |
4151 | MediaManager::SanitizeDeviceIds(int64_t aSinceWhen) { |
4152 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4152; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4153 | LOG("%s: sinceWhen = %" PRId64"l" "d", __FUNCTION__, aSinceWhen); |
4154 | |
4155 | media::SanitizeOriginKeys(aSinceWhen, false); // we fire and forget |
4156 | return NS_OK; |
4157 | } |
4158 | |
4159 | void MediaManager::StopScreensharing(uint64_t aWindowID) { |
4160 | // We need to stop window/screensharing for all streams in this innerwindow. |
4161 | |
4162 | if (RefPtr<GetUserMediaWindowListener> listener = |
4163 | GetWindowListener(aWindowID)) { |
4164 | listener->StopSharing(); |
4165 | } |
4166 | } |
4167 | |
4168 | bool MediaManager::IsActivelyCapturingOrHasAPermission(uint64_t aWindowId) { |
4169 | // Does page currently have a gUM stream active? |
4170 | |
4171 | nsCOMPtr<nsIArray> array; |
4172 | GetActiveMediaCaptureWindows(getter_AddRefs(array)); |
4173 | uint32_t len; |
4174 | array->GetLength(&len); |
4175 | for (uint32_t i = 0; i < len; i++) { |
4176 | nsCOMPtr<nsPIDOMWindowInner> win; |
4177 | array->QueryElementAt(i, NS_GET_IID(nsPIDOMWindowInner)(nsPIDOMWindowInner::COMTypeInfo<nsPIDOMWindowInner, void> ::kIID), |
4178 | getter_AddRefs(win)); |
4179 | if (win && win->WindowID() == aWindowId) { |
4180 | return true; |
4181 | } |
4182 | } |
4183 | |
4184 | // Or are persistent permissions (audio or video) granted? |
4185 | |
4186 | return GetPersistentPermissions(aWindowId) |
4187 | .map([](auto&& aState) { |
4188 | return aState.mMicrophonePermission == |
4189 | PersistentPermissionState::Allow || |
4190 | aState.mCameraPermission == PersistentPermissionState::Allow; |
4191 | }) |
4192 | .unwrapOr(false); |
4193 | } |
4194 | |
4195 | DeviceListener::DeviceListener() |
4196 | : mStopped(false), |
4197 | mMainThreadCheck(nullptr), |
4198 | mPrincipalHandle(PRINCIPAL_HANDLE_NONEnullptr), |
4199 | mWindowListener(nullptr) {} |
4200 | |
4201 | void DeviceListener::Register(GetUserMediaWindowListener* aListener) { |
4202 | LOG("DeviceListener %p registering with window listener %p", this, aListener); |
4203 | |
4204 | MOZ_ASSERT(aListener, "No listener")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aListener" " (" "No listener" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4204); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aListener" ") (" "No listener" ")"); do { *((volatile int*)__null) = 4204; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
4205 | MOZ_ASSERT(!mWindowListener, "Already registered")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mWindowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mWindowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mWindowListener" " (" "Already registered" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4205); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mWindowListener" ") (" "Already registered" ")"); do { *((volatile int*)__null ) = 4205; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4206 | MOZ_ASSERT(!Activated(), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!Activated()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!Activated()" " (" "Already activated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!Activated()" ") (" "Already activated" ")"); do { *((volatile int*)__null ) = 4206; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4207 | |
4208 | mPrincipalHandle = aListener->GetPrincipalHandle(); |
4209 | mWindowListener = aListener; |
4210 | } |
4211 | |
4212 | void DeviceListener::Activate(RefPtr<LocalMediaDevice> aDevice, |
4213 | RefPtr<LocalTrackSource> aTrackSource, |
4214 | bool aStartMuted) { |
4215 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4215; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4216 | |
4217 | LOG("DeviceListener %p activating %s device %p", this, |
4218 | dom::GetEnumString(aDevice->Kind()).get(), aDevice.get()); |
4219 | |
4220 | MOZ_ASSERT(!mStopped, "Cannot activate stopped device listener")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mStopped" " (" "Cannot activate stopped device listener" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4220); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mStopped" ") (" "Cannot activate stopped device listener" ")"); do { *((volatile int*)__null) = 4220; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4221 | MOZ_ASSERT(!Activated(), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!Activated()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!Activated()" " (" "Already activated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!Activated()" ") (" "Already activated" ")"); do { *((volatile int*)__null ) = 4221; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4222 | |
4223 | mMainThreadCheck = PR_GetCurrentThread(); |
4224 | bool offWhileDisabled = |
4225 | (aDevice->GetMediaSource() == MediaSourceEnum::Microphone && |
4226 | Preferences::GetBool( |
4227 | "media.getusermedia.microphone.off_while_disabled.enabled", true)) || |
4228 | (aDevice->GetMediaSource() == MediaSourceEnum::Camera && |
4229 | Preferences::GetBool( |
4230 | "media.getusermedia.camera.off_while_disabled.enabled", true)); |
4231 | |
4232 | if (MediaEventSource<void>* event = aDevice->Source()->CaptureEndedEvent()) { |
4233 | mCaptureEndedListener = event->Connect(AbstractThread::MainThread(), this, |
4234 | &DeviceListener::Stop); |
4235 | } |
4236 | |
4237 | mDeviceState = MakeUnique<DeviceState>( |
4238 | std::move(aDevice), std::move(aTrackSource), offWhileDisabled); |
4239 | mDeviceState->mDeviceMuted = aStartMuted; |
4240 | if (aStartMuted) { |
4241 | mDeviceState->mTrackSource->Mute(); |
4242 | } |
4243 | } |
4244 | |
4245 | RefPtr<DeviceListener::DeviceListenerPromise> |
4246 | DeviceListener::InitializeAsync() { |
4247 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4247); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4247; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4248 | MOZ_DIAGNOSTIC_ASSERT(!mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mStopped", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4248); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mStopped" ")"); do { *((volatile int*)__null) = 4248; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4249 | |
4250 | return MediaManager::Dispatch<DeviceListenerPromise>( |
4251 | __func__, |
4252 | [principal = GetPrincipalHandle(), device = mDeviceState->mDevice, |
4253 | track = mDeviceState->mTrackSource->mTrack, |
4254 | deviceMuted = mDeviceState->mDeviceMuted]( |
4255 | MozPromiseHolder<DeviceListenerPromise>& aHolder) { |
4256 | auto kind = device->Kind(); |
4257 | device->SetTrack(track, principal); |
4258 | nsresult rv = deviceMuted ? NS_OK : device->Start(); |
4259 | if (kind == MediaDeviceKind::Audioinput || |
4260 | kind == MediaDeviceKind::Videoinput) { |
4261 | if ((rv == NS_ERROR_NOT_AVAILABLE && |
4262 | kind == MediaDeviceKind::Audioinput) || |
4263 | (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && kind == MediaDeviceKind::Videoinput)) { |
4264 | PR_Sleep(200); |
4265 | rv = device->Start(); |
4266 | } |
4267 | if (rv == NS_ERROR_NOT_AVAILABLE && |
4268 | kind == MediaDeviceKind::Audioinput) { |
4269 | nsCString log; |
4270 | log.AssignLiteral("Concurrent mic process limit."); |
4271 | aHolder.Reject(MakeRefPtr<MediaMgrError>( |
4272 | MediaMgrError::Name::NotReadableError, |
4273 | std::move(log)), |
4274 | __func__); |
4275 | return; |
4276 | } |
4277 | } |
4278 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4279 | nsCString log; |
4280 | log.AppendPrintf("Starting %s failed", |
4281 | dom::GetEnumString(kind).get()); |
4282 | aHolder.Reject( |
4283 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError, |
4284 | std::move(log)), |
4285 | __func__); |
4286 | return; |
4287 | } |
4288 | LOG("started %s device %p", dom::GetEnumString(kind).get(), |
4289 | device.get()); |
4290 | aHolder.Resolve(true, __func__); |
4291 | }) |
4292 | ->Then( |
4293 | GetMainThreadSerialEventTarget(), __func__, |
4294 | [self = RefPtr<DeviceListener>(this), this]() { |
4295 | if (mStopped) { |
4296 | // We were shut down during the async init |
4297 | return DeviceListenerPromise::CreateAndResolve(true, __func__); |
4298 | } |
4299 | |
4300 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mTrackEnabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mTrackEnabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mTrackEnabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mDeviceState->mTrackEnabled", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4300); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mTrackEnabled" ")"); do { *((volatile int*)__null) = 4300; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4301 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mDeviceEnabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mDeviceEnabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mDeviceEnabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mDeviceState->mDeviceEnabled", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4301); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mDeviceEnabled" ")"); do { *((volatile int*)__null) = 4301; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4302 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mStopped)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDeviceState->mStopped" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4302); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mStopped" ")"); do { *((volatile int*)__null) = 4302; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4303 | |
4304 | mDeviceState->mDeviceEnabled = true; |
4305 | mDeviceState->mTrackEnabled = true; |
4306 | mDeviceState->mTrackEnabledTime = TimeStamp::Now(); |
4307 | return DeviceListenerPromise::CreateAndResolve(true, __func__); |
4308 | }, |
4309 | [self = RefPtr<DeviceListener>(this), |
4310 | this](RefPtr<MediaMgrError>&& aResult) { |
4311 | if (mStopped) { |
4312 | return DeviceListenerPromise::CreateAndReject(std::move(aResult), |
4313 | __func__); |
4314 | } |
4315 | |
4316 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mTrackEnabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mTrackEnabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mTrackEnabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mDeviceState->mTrackEnabled", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4316); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mTrackEnabled" ")"); do { *((volatile int*)__null) = 4316; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4317 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mDeviceEnabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mDeviceEnabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mDeviceEnabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mDeviceState->mDeviceEnabled", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4317); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mDeviceEnabled" ")"); do { *((volatile int*)__null) = 4317; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4318 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mStopped)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDeviceState->mStopped" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4318); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mStopped" ")"); do { *((volatile int*)__null) = 4318; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4319 | |
4320 | Stop(); |
4321 | return DeviceListenerPromise::CreateAndReject(std::move(aResult), |
4322 | __func__); |
4323 | }); |
4324 | } |
4325 | |
4326 | void DeviceListener::Stop() { |
4327 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4327; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4328 | |
4329 | if (mStopped) { |
4330 | return; |
4331 | } |
4332 | mStopped = true; |
4333 | |
4334 | LOG("DeviceListener %p stopping", this); |
4335 | |
4336 | if (mDeviceState) { |
4337 | mDeviceState->mDisableTimer->Cancel(); |
4338 | |
4339 | if (mDeviceState->mStopped) { |
4340 | // device already stopped. |
4341 | return; |
4342 | } |
4343 | mDeviceState->mStopped = true; |
4344 | |
4345 | mDeviceState->mTrackSource->Stop(); |
4346 | |
4347 | MediaManager::Dispatch(NewTaskFrom([device = mDeviceState->mDevice]() { |
4348 | device->Stop(); |
4349 | device->Deallocate(); |
4350 | })); |
4351 | |
4352 | mWindowListener->ChromeAffectingStateChanged(); |
4353 | } |
4354 | |
4355 | mCaptureEndedListener.DisconnectIfExists(); |
4356 | |
4357 | // Keep a strong ref to the removed window listener. |
4358 | RefPtr<GetUserMediaWindowListener> windowListener = mWindowListener; |
4359 | mWindowListener = nullptr; |
4360 | windowListener->Remove(this); |
4361 | } |
4362 | |
4363 | void DeviceListener::GetSettings(MediaTrackSettings& aOutSettings) const { |
4364 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4364; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4365 | LocalMediaDevice* device = GetDevice(); |
4366 | device->GetSettings(aOutSettings); |
4367 | |
4368 | MediaSourceEnum mediaSource = device->GetMediaSource(); |
4369 | if (mediaSource == MediaSourceEnum::Camera || |
4370 | mediaSource == MediaSourceEnum::Microphone) { |
4371 | aOutSettings.mDeviceId.Construct(device->mID); |
4372 | aOutSettings.mGroupId.Construct(device->mGroupID); |
4373 | } |
4374 | } |
4375 | |
4376 | void DeviceListener::GetCapabilities( |
4377 | MediaTrackCapabilities& aOutCapabilities) const { |
4378 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4378; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4379 | LocalMediaDevice* device = GetDevice(); |
4380 | device->GetCapabilities(aOutCapabilities); |
4381 | |
4382 | MediaSourceEnum mediaSource = device->GetMediaSource(); |
4383 | if (mediaSource == MediaSourceEnum::Camera || |
4384 | mediaSource == MediaSourceEnum::Microphone) { |
4385 | aOutCapabilities.mDeviceId.Construct(device->mID); |
4386 | aOutCapabilities.mGroupId.Construct(device->mGroupID); |
4387 | } |
4388 | } |
4389 | |
4390 | auto DeviceListener::UpdateDevice(bool aOn) -> RefPtr<DeviceOperationPromise> { |
4391 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4391; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4392 | RefPtr<DeviceListener> self = this; |
4393 | DeviceState& state = *mDeviceState; |
4394 | return MediaManager::Dispatch<DeviceOperationPromise>( |
4395 | __func__, |
4396 | [self, device = state.mDevice, |
4397 | aOn](MozPromiseHolder<DeviceOperationPromise>& h) { |
4398 | LOG("Turning %s device (%s)", aOn ? "on" : "off", |
4399 | NS_ConvertUTF16toUTF8(device->mName).get()); |
4400 | h.Resolve(aOn ? device->Start() : device->Stop(), __func__); |
4401 | }) |
4402 | ->Then( |
4403 | GetMainThreadSerialEventTarget(), __func__, |
4404 | [self, this, &state, aOn](nsresult aResult) { |
4405 | if (state.mStopped) { |
4406 | // Device was stopped on main thread during the operation. Done. |
4407 | return DeviceOperationPromise::CreateAndResolve(aResult, |
4408 | __func__); |
4409 | } |
4410 | LOG("DeviceListener %p turning %s %s input device %s", this, |
4411 | aOn ? "on" : "off", |
4412 | dom::GetEnumString(GetDevice()->Kind()).get(), |
4413 | NS_SUCCEEDED(aResult)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResult)), 1))) ? "succeeded" : "failed"); |
4414 | |
4415 | if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0))) && aResult != NS_ERROR_ABORT) { |
4416 | // This path handles errors from starting or stopping the |
4417 | // device. NS_ERROR_ABORT are for cases where *we* aborted. They |
4418 | // need graceful handling. |
4419 | if (aOn) { |
4420 | // Starting the device failed. Stopping the track here will |
4421 | // make the MediaStreamTrack end after a pass through the |
4422 | // MediaTrackGraph. |
4423 | Stop(); |
4424 | } else { |
4425 | // Stopping the device failed. This is odd, but not fatal. |
4426 | MOZ_ASSERT_UNREACHABLE("The device should be stoppable")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "The device should be stoppable" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4426); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The device should be stoppable" ")" ); do { *((volatile int*)__null) = 4426; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4427 | } |
4428 | } |
4429 | return DeviceOperationPromise::CreateAndResolve(aResult, __func__); |
4430 | }, |
4431 | []() { |
4432 | MOZ_ASSERT_UNREACHABLE("Unexpected and unhandled reject")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4432); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject" ")"); do { *((volatile int*)__null) = 4432; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4433 | return DeviceOperationPromise::CreateAndReject(false, __func__); |
4434 | }); |
4435 | } |
4436 | |
4437 | void DeviceListener::SetDeviceEnabled(bool aEnable) { |
4438 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4438; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4439 | MOZ_ASSERT(Activated(), "No device to set enabled state for")do { static_assert( mozilla::detail::AssertionConditionType< decltype(Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(Activated()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("Activated()" " (" "No device to set enabled state for" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4439); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Activated()" ") (" "No device to set enabled state for" ")"); do { *((volatile int*)__null) = 4439; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4440 | |
4441 | DeviceState& state = *mDeviceState; |
4442 | |
4443 | LOG("DeviceListener %p %s %s device", this, |
4444 | aEnable ? "enabling" : "disabling", |
4445 | dom::GetEnumString(GetDevice()->Kind()).get()); |
4446 | |
4447 | state.mTrackEnabled = aEnable; |
4448 | |
4449 | if (state.mStopped) { |
4450 | // Device terminally stopped. Updating device state is pointless. |
4451 | return; |
4452 | } |
4453 | |
4454 | if (state.mOperationInProgress) { |
4455 | // If a timer is in progress, it needs to be canceled now so the next |
4456 | // DisableTrack() gets a fresh start. Canceling will trigger another |
4457 | // operation. |
4458 | state.mDisableTimer->Cancel(); |
4459 | return; |
4460 | } |
4461 | |
4462 | if (state.mDeviceEnabled == aEnable) { |
4463 | // Device is already in the desired state. |
4464 | return; |
4465 | } |
4466 | |
4467 | // All paths from here on must end in setting |
4468 | // `state.mOperationInProgress` to false. |
4469 | state.mOperationInProgress = true; |
4470 | |
4471 | RefPtr<MediaTimerPromise> timerPromise; |
4472 | if (aEnable) { |
4473 | timerPromise = MediaTimerPromise::CreateAndResolve(true, __func__); |
4474 | state.mTrackEnabledTime = TimeStamp::Now(); |
4475 | } else { |
4476 | const TimeDuration maxDelay = |
4477 | TimeDuration::FromMilliseconds(Preferences::GetUint( |
4478 | GetDevice()->Kind() == MediaDeviceKind::Audioinput |
4479 | ? "media.getusermedia.microphone.off_while_disabled.delay_ms" |
4480 | : "media.getusermedia.camera.off_while_disabled.delay_ms", |
4481 | 3000)); |
4482 | const TimeDuration durationEnabled = |
4483 | TimeStamp::Now() - state.mTrackEnabledTime; |
4484 | const TimeDuration delay = TimeDuration::Max( |
4485 | TimeDuration::FromMilliseconds(0), maxDelay - durationEnabled); |
4486 | timerPromise = state.mDisableTimer->WaitFor(delay, __func__); |
4487 | } |
4488 | |
4489 | RefPtr<DeviceListener> self = this; |
4490 | timerPromise |
4491 | ->Then( |
4492 | GetMainThreadSerialEventTarget(), __func__, |
4493 | [self, this, &state, aEnable]() mutable { |
4494 | MOZ_ASSERT(state.mDeviceEnabled != aEnable,do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mDeviceEnabled != aEnable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled != aEnable ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "state.mDeviceEnabled != aEnable" " (" "Device operation hasn't started" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4495); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled != aEnable" ") (" "Device operation hasn't started" ")"); do { *((volatile int*)__null) = 4495; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
4495 | "Device operation hasn't started")do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mDeviceEnabled != aEnable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled != aEnable ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "state.mDeviceEnabled != aEnable" " (" "Device operation hasn't started" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4495); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled != aEnable" ") (" "Device operation hasn't started" ")"); do { *((volatile int*)__null) = 4495; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4496 | MOZ_ASSERT(state.mOperationInProgress,do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mOperationInProgress)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mOperationInProgress)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mOperationInProgress" " (" "It's our responsibility to reset the inProgress state" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4497); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mOperationInProgress" ") (" "It's our responsibility to reset the inProgress state" ")"); do { *((volatile int*)__null) = 4497; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4497 | "It's our responsibility to reset the inProgress state")do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mOperationInProgress)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mOperationInProgress)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mOperationInProgress" " (" "It's our responsibility to reset the inProgress state" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4497); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mOperationInProgress" ") (" "It's our responsibility to reset the inProgress state" ")"); do { *((volatile int*)__null) = 4497; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4498 | |
4499 | LOG("DeviceListener %p %s %s device - starting device operation", |
4500 | this, aEnable ? "enabling" : "disabling", |
4501 | dom::GetEnumString(GetDevice()->Kind()).get()); |
4502 | |
4503 | if (state.mStopped) { |
4504 | // Source was stopped between timer resolving and this runnable. |
4505 | return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT, |
4506 | __func__); |
4507 | } |
4508 | |
4509 | state.mDeviceEnabled = aEnable; |
4510 | |
4511 | if (mWindowListener) { |
4512 | mWindowListener->ChromeAffectingStateChanged(); |
4513 | } |
4514 | if (!state.mOffWhileDisabled || state.mDeviceMuted) { |
4515 | // If the feature to turn a device off while disabled is itself |
4516 | // disabled, or the device is currently user agent muted, then |
4517 | // we shortcut the device operation and tell the |
4518 | // ux-updating code that everything went fine. |
4519 | return DeviceOperationPromise::CreateAndResolve(NS_OK, __func__); |
4520 | } |
4521 | return UpdateDevice(aEnable); |
4522 | }, |
4523 | []() { |
4524 | // Timer was canceled by us. We signal this with NS_ERROR_ABORT. |
4525 | return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT, |
4526 | __func__); |
4527 | }) |
4528 | ->Then( |
4529 | GetMainThreadSerialEventTarget(), __func__, |
4530 | [self, this, &state, aEnable](nsresult aResult) mutable { |
4531 | MOZ_ASSERT_IF(aResult != NS_ERROR_ABORT,do { if (aResult != NS_ERROR_ABORT) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(state.mDeviceEnabled == aEnable)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled == aEnable)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mDeviceEnabled == aEnable" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled == aEnable" ")"); do { *((volatile int*)__null) = 4532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
4532 | state.mDeviceEnabled == aEnable)do { if (aResult != NS_ERROR_ABORT) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(state.mDeviceEnabled == aEnable)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled == aEnable)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mDeviceEnabled == aEnable" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled == aEnable" ")"); do { *((volatile int*)__null) = 4532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
4533 | MOZ_ASSERT(state.mOperationInProgress)do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mOperationInProgress)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mOperationInProgress)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mOperationInProgress" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4533); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mOperationInProgress" ")"); do { *((volatile int*)__null) = 4533; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4534 | state.mOperationInProgress = false; |
4535 | |
4536 | if (state.mStopped) { |
4537 | // Device was stopped on main thread during the operation. |
4538 | // Nothing to do. |
4539 | return; |
4540 | } |
4541 | |
4542 | if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0))) && aResult != NS_ERROR_ABORT && !aEnable) { |
4543 | // To keep our internal state sane in this case, we disallow |
4544 | // future stops due to disable. |
4545 | state.mOffWhileDisabled = false; |
4546 | return; |
4547 | } |
4548 | |
4549 | // This path is for a device operation aResult that was success or |
4550 | // NS_ERROR_ABORT (*we* canceled the operation). |
4551 | // At this point we have to follow up on the intended state, i.e., |
4552 | // update the device state if the track state changed in the |
4553 | // meantime. |
4554 | |
4555 | if (state.mTrackEnabled != state.mDeviceEnabled) { |
4556 | // Track state changed during this operation. We'll start over. |
4557 | SetDeviceEnabled(state.mTrackEnabled); |
4558 | } |
4559 | }, |
4560 | []() { MOZ_ASSERT_UNREACHABLE("Unexpected and unhandled reject")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4560); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject" ")"); do { *((volatile int*)__null) = 4560; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); }); |
4561 | } |
4562 | |
4563 | void DeviceListener::SetDeviceMuted(bool aMute) { |
4564 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4564; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4565 | MOZ_ASSERT(Activated(), "No device to set muted state for")do { static_assert( mozilla::detail::AssertionConditionType< decltype(Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(Activated()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("Activated()" " (" "No device to set muted state for" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Activated()" ") (" "No device to set muted state for" ")"); do { *((volatile int*)__null) = 4565; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4566 | |
4567 | DeviceState& state = *mDeviceState; |
4568 | |
4569 | LOG("DeviceListener %p %s %s device", this, aMute ? "muting" : "unmuting", |
4570 | dom::GetEnumString(GetDevice()->Kind()).get()); |
4571 | |
4572 | if (state.mStopped) { |
4573 | // Device terminally stopped. Updating device state is pointless. |
4574 | return; |
4575 | } |
4576 | |
4577 | if (state.mDeviceMuted == aMute) { |
4578 | // Device is already in the desired state. |
4579 | return; |
4580 | } |
4581 | |
4582 | LOG("DeviceListener %p %s %s device - starting device operation", this, |
4583 | aMute ? "muting" : "unmuting", |
4584 | dom::GetEnumString(GetDevice()->Kind()).get()); |
4585 | |
4586 | state.mDeviceMuted = aMute; |
4587 | |
4588 | if (mWindowListener) { |
4589 | mWindowListener->ChromeAffectingStateChanged(); |
4590 | } |
4591 | // Update trackSource to fire mute/unmute events on all its tracks |
4592 | if (aMute) { |
4593 | state.mTrackSource->Mute(); |
4594 | } else { |
4595 | state.mTrackSource->Unmute(); |
4596 | } |
4597 | if (!state.mOffWhileDisabled || !state.mDeviceEnabled) { |
4598 | // If the pref to turn the underlying device is itself off, or the device |
4599 | // is already off, it's unecessary to do anything else. |
4600 | return; |
4601 | } |
4602 | UpdateDevice(!aMute); |
4603 | } |
4604 | |
4605 | void DeviceListener::MuteOrUnmuteCamera(bool aMute) { |
4606 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4606; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4607 | |
4608 | if (mStopped) { |
4609 | return; |
4610 | } |
4611 | |
4612 | MOZ_RELEASE_ASSERT(mWindowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4612); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mWindowListener" ")"); do { *((volatile int*)__null) = 4612; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4613 | LOG("DeviceListener %p MuteOrUnmuteCamera: %s", this, |
4614 | aMute ? "mute" : "unmute"); |
4615 | |
4616 | if (GetDevice() && |
4617 | (GetDevice()->GetMediaSource() == MediaSourceEnum::Camera)) { |
4618 | SetDeviceMuted(aMute); |
4619 | } |
4620 | } |
4621 | |
4622 | void DeviceListener::MuteOrUnmuteMicrophone(bool aMute) { |
4623 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4623); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4623; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4624 | |
4625 | if (mStopped) { |
4626 | return; |
4627 | } |
4628 | |
4629 | MOZ_RELEASE_ASSERT(mWindowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4629); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mWindowListener" ")"); do { *((volatile int*)__null) = 4629; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4630 | LOG("DeviceListener %p MuteOrUnmuteMicrophone: %s", this, |
4631 | aMute ? "mute" : "unmute"); |
4632 | |
4633 | if (GetDevice() && |
4634 | (GetDevice()->GetMediaSource() == MediaSourceEnum::Microphone)) { |
4635 | SetDeviceMuted(aMute); |
4636 | } |
4637 | } |
4638 | |
4639 | bool DeviceListener::CapturingVideo() const { |
4640 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4640; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4641 | return Activated() && mDeviceState && !mDeviceState->mStopped && |
4642 | MediaEngineSource::IsVideo(GetDevice()->GetMediaSource()) && |
4643 | (!GetDevice()->IsFake() || |
4644 | Preferences::GetBool("media.navigator.permission.fake")); |
4645 | } |
4646 | |
4647 | bool DeviceListener::CapturingAudio() const { |
4648 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4648; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4649 | return Activated() && mDeviceState && !mDeviceState->mStopped && |
4650 | MediaEngineSource::IsAudio(GetDevice()->GetMediaSource()) && |
4651 | (!GetDevice()->IsFake() || |
4652 | Preferences::GetBool("media.navigator.permission.fake")); |
4653 | } |
4654 | |
4655 | CaptureState DeviceListener::CapturingSource(MediaSourceEnum aSource) const { |
4656 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4656; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4657 | if (GetDevice()->GetMediaSource() != aSource) { |
4658 | // This DeviceListener doesn't capture a matching source |
4659 | return CaptureState::Off; |
4660 | } |
4661 | |
4662 | if (mDeviceState->mStopped) { |
4663 | // The source is a match but has been permanently stopped |
4664 | return CaptureState::Off; |
4665 | } |
4666 | |
4667 | if ((aSource == MediaSourceEnum::Camera || |
4668 | aSource == MediaSourceEnum::Microphone) && |
4669 | GetDevice()->IsFake() && |
4670 | !Preferences::GetBool("media.navigator.permission.fake")) { |
4671 | // Fake Camera and Microphone only count if there is no fake permission |
4672 | return CaptureState::Off; |
4673 | } |
4674 | |
4675 | // Source is a match and is active and unmuted |
4676 | |
4677 | if (mDeviceState->mDeviceEnabled && !mDeviceState->mDeviceMuted) { |
4678 | return CaptureState::Enabled; |
4679 | } |
4680 | |
4681 | return CaptureState::Disabled; |
4682 | } |
4683 | |
4684 | RefPtr<DeviceListener::DeviceListenerPromise> DeviceListener::ApplyConstraints( |
4685 | const MediaTrackConstraints& aConstraints, CallerType aCallerType) { |
4686 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4686; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4687 | |
4688 | if (mStopped || mDeviceState->mStopped) { |
4689 | LOG("DeviceListener %p %s device applyConstraints, but device is stopped", |
4690 | this, dom::GetEnumString(GetDevice()->Kind()).get()); |
4691 | return DeviceListenerPromise::CreateAndResolve(false, __func__); |
4692 | } |
4693 | |
4694 | MediaManager* mgr = MediaManager::GetIfExists(); |
4695 | if (!mgr) { |
4696 | return DeviceListenerPromise::CreateAndResolve(false, __func__); |
4697 | } |
4698 | |
4699 | return MediaManager::Dispatch<DeviceListenerPromise>( |
4700 | __func__, [device = mDeviceState->mDevice, aConstraints, aCallerType]( |
4701 | MozPromiseHolder<DeviceListenerPromise>& aHolder) mutable { |
4702 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 4702; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4703 | MediaManager* mgr = MediaManager::GetIfExists(); |
4704 | MOZ_RELEASE_ASSERT(mgr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mgr)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(mgr))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mgr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4704); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mgr" ")"); do { *((volatile int*)__null) = 4704; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); // Must exist while media thread is alive |
4705 | const char* badConstraint = nullptr; |
4706 | nsresult rv = |
4707 | device->Reconfigure(aConstraints, mgr->mPrefs, &badConstraint); |
4708 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4709 | if (rv == NS_ERROR_INVALID_ARG) { |
4710 | // Reconfigure failed due to constraints |
4711 | if (!badConstraint) { |
4712 | nsTArray<RefPtr<LocalMediaDevice>> devices; |
4713 | devices.AppendElement(device); |
4714 | badConstraint = MediaConstraintsHelper::SelectSettings( |
4715 | NormalizedConstraints(aConstraints), devices, aCallerType); |
4716 | } |
4717 | } else { |
4718 | // Unexpected. ApplyConstraints* cannot fail with any other error. |
4719 | badConstraint = ""; |
4720 | LOG("ApplyConstraints-Task: Unexpected fail %" PRIx32"x", |
4721 | static_cast<uint32_t>(rv)); |
4722 | } |
4723 | |
4724 | aHolder.Reject(MakeRefPtr<MediaMgrError>( |
4725 | MediaMgrError::Name::OverconstrainedError, "", |
4726 | NS_ConvertASCIItoUTF16(badConstraint)), |
4727 | __func__); |
4728 | return; |
4729 | } |
4730 | // Reconfigure was successful |
4731 | aHolder.Resolve(false, __func__); |
4732 | }); |
4733 | } |
4734 | |
4735 | PrincipalHandle DeviceListener::GetPrincipalHandle() const { |
4736 | return mPrincipalHandle; |
4737 | } |
4738 | |
4739 | void GetUserMediaWindowListener::StopSharing() { |
4740 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4740; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4741 | |
4742 | for (auto& l : mActiveListeners.Clone()) { |
4743 | MediaSourceEnum source = l->GetDevice()->GetMediaSource(); |
4744 | if (source == MediaSourceEnum::Screen || |
4745 | source == MediaSourceEnum::Window || |
4746 | source == MediaSourceEnum::AudioCapture) { |
4747 | l->Stop(); |
4748 | } |
4749 | } |
4750 | } |
4751 | |
4752 | void GetUserMediaWindowListener::StopRawID(const nsString& removedDeviceID) { |
4753 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4753; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4754 | |
4755 | for (auto& l : mActiveListeners.Clone()) { |
4756 | if (removedDeviceID.Equals(l->GetDevice()->RawID())) { |
4757 | l->Stop(); |
4758 | } |
4759 | } |
4760 | } |
4761 | |
4762 | void GetUserMediaWindowListener::MuteOrUnmuteCameras(bool aMute) { |
4763 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4763); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4763; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4764 | |
4765 | if (mCamerasAreMuted == aMute) { |
4766 | return; |
4767 | } |
4768 | mCamerasAreMuted = aMute; |
4769 | |
4770 | for (auto& l : mActiveListeners) { |
4771 | if (l->GetDevice()->Kind() == MediaDeviceKind::Videoinput) { |
4772 | l->MuteOrUnmuteCamera(aMute); |
4773 | } |
4774 | } |
4775 | } |
4776 | |
4777 | void GetUserMediaWindowListener::MuteOrUnmuteMicrophones(bool aMute) { |
4778 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4778); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4778; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4779 | |
4780 | if (mMicrophonesAreMuted == aMute) { |
4781 | return; |
4782 | } |
4783 | mMicrophonesAreMuted = aMute; |
4784 | |
4785 | for (auto& l : mActiveListeners) { |
4786 | if (l->GetDevice()->Kind() == MediaDeviceKind::Audioinput) { |
4787 | l->MuteOrUnmuteMicrophone(aMute); |
4788 | } |
4789 | } |
4790 | } |
4791 | |
4792 | void GetUserMediaWindowListener::ChromeAffectingStateChanged() { |
4793 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4793; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4794 | |
4795 | // We wait until stable state before notifying chrome so chrome only does |
4796 | // one update if more updates happen in this event loop. |
4797 | |
4798 | if (mChromeNotificationTaskPosted) { |
4799 | return; |
4800 | } |
4801 | |
4802 | nsCOMPtr<nsIRunnable> runnable = |
4803 | NewRunnableMethod("GetUserMediaWindowListener::NotifyChrome", this, |
4804 | &GetUserMediaWindowListener::NotifyChrome); |
4805 | nsContentUtils::RunInStableState(runnable.forget()); |
4806 | mChromeNotificationTaskPosted = true; |
4807 | } |
4808 | |
4809 | void GetUserMediaWindowListener::NotifyChrome() { |
4810 | MOZ_ASSERT(mChromeNotificationTaskPosted)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChromeNotificationTaskPosted)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChromeNotificationTaskPosted ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mChromeNotificationTaskPosted", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChromeNotificationTaskPosted" ")"); do { *((volatile int*)__null) = 4810; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4811 | mChromeNotificationTaskPosted = false; |
4812 | |
4813 | NS_DispatchToMainThread(NS_NewRunnableFunction( |
4814 | "MediaManager::NotifyChrome", [windowID = mWindowID]() { |
4815 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(windowID); |
4816 | if (!window) { |
4817 | MOZ_ASSERT_UNREACHABLE("Should have window")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Should have window" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Should have window" ")"); do { * ((volatile int*)__null) = 4817; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
4818 | return; |
4819 | } |
4820 | |
4821 | nsresult rv = MediaManager::NotifyRecordingStatusChange(window); |
4822 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4823 | MOZ_ASSERT_UNREACHABLE("Should be able to notify chrome")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Should be able to notify chrome" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Should be able to notify chrome" ")"); do { *((volatile int*)__null) = 4823; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4824 | return; |
4825 | } |
4826 | })); |
4827 | } |
4828 | |
4829 | #undef LOG |
4830 | |
4831 | } // namespace mozilla |