File: | var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp |
Warning: | line 2822, column 12 Value stored to 'rv' during its initialization is never read |
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::MediaTrackConstraints; |
178 | using dom::MediaTrackConstraintSet; |
179 | using dom::MediaTrackSettings; |
180 | using dom::OwningBooleanOrMediaTrackConstraints; |
181 | using dom::OwningStringOrStringSequence; |
182 | using dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters; |
183 | using dom::Promise; |
184 | using dom::Sequence; |
185 | using dom::UserActivation; |
186 | using dom::WindowGlobalChild; |
187 | using ConstDeviceSetPromise = MediaManager::ConstDeviceSetPromise; |
188 | using DeviceSetPromise = MediaManager::DeviceSetPromise; |
189 | using LocalDevicePromise = MediaManager::LocalDevicePromise; |
190 | using LocalDeviceSetPromise = MediaManager::LocalDeviceSetPromise; |
191 | using LocalMediaDeviceSetRefCnt = MediaManager::LocalMediaDeviceSetRefCnt; |
192 | using MediaDeviceSetRefCnt = MediaManager::MediaDeviceSetRefCnt; |
193 | using media::NewRunnableFrom; |
194 | using media::NewTaskFrom; |
195 | using media::Refcountable; |
196 | |
197 | // Whether main thread actions of MediaManager shutdown (except for clearing |
198 | // of sSingleton) have completed. |
199 | static bool sHasMainThreadShutdown; |
200 | |
201 | struct DeviceState { |
202 | DeviceState(RefPtr<LocalMediaDevice> aDevice, |
203 | RefPtr<LocalTrackSource> aTrackSource, bool aOffWhileDisabled) |
204 | : mOffWhileDisabled(aOffWhileDisabled), |
205 | mDevice(std::move(aDevice)), |
206 | mTrackSource(std::move(aTrackSource)) { |
207 | MOZ_ASSERT(mDevice)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mDevice)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mDevice))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mDevice", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 207); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDevice" ")" ); do { *((volatile int*)__null) = 207; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
208 | MOZ_ASSERT(mTrackSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mTrackSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mTrackSource))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mTrackSource", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTrackSource" ")"); do { *((volatile int*)__null) = 208; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
209 | } |
210 | |
211 | // true if we have stopped mDevice, this is a terminal state. |
212 | // MainThread only. |
213 | bool mStopped = false; |
214 | |
215 | // true if mDevice is currently enabled. |
216 | // A device must be both enabled and unmuted to be turned on and capturing. |
217 | // MainThread only. |
218 | bool mDeviceEnabled = false; |
219 | |
220 | // true if mDevice is currently muted. |
221 | // A device that is either muted or disabled is turned off and not capturing. |
222 | // MainThread only. |
223 | bool mDeviceMuted; |
224 | |
225 | // true if the application has currently enabled mDevice. |
226 | // MainThread only. |
227 | bool mTrackEnabled = false; |
228 | |
229 | // Time when the application last enabled mDevice. |
230 | // MainThread only. |
231 | TimeStamp mTrackEnabledTime; |
232 | |
233 | // true if an operation to Start() or Stop() mDevice has been dispatched to |
234 | // the media thread and is not finished yet. |
235 | // MainThread only. |
236 | bool mOperationInProgress = false; |
237 | |
238 | // true if we are allowed to turn off the underlying source while all tracks |
239 | // are disabled. Only affects disabling; always turns off on user-agent mute. |
240 | // MainThread only. |
241 | bool mOffWhileDisabled = false; |
242 | |
243 | // Timer triggered by a MediaStreamTrackSource signaling that all tracks got |
244 | // disabled. When the timer fires we initiate Stop()ing mDevice. |
245 | // If set we allow dynamically stopping and starting mDevice. |
246 | // Any thread. |
247 | const RefPtr<MediaTimer> mDisableTimer = new MediaTimer(); |
248 | |
249 | // The underlying device we keep state for. Always non-null. |
250 | // Threadsafe access, but see method declarations for individual constraints. |
251 | const RefPtr<LocalMediaDevice> mDevice; |
252 | |
253 | // The MediaStreamTrackSource for any tracks (original and clones) originating |
254 | // from this device. Always non-null. Threadsafe access, but see method |
255 | // declarations for individual constraints. |
256 | const RefPtr<LocalTrackSource> mTrackSource; |
257 | }; |
258 | |
259 | /** |
260 | * This mimics the capture state from nsIMediaManagerService. |
261 | */ |
262 | enum class CaptureState : uint16_t { |
263 | Off = nsIMediaManagerService::STATE_NOCAPTURE, |
264 | Enabled = nsIMediaManagerService::STATE_CAPTURE_ENABLED, |
265 | Disabled = nsIMediaManagerService::STATE_CAPTURE_DISABLED, |
266 | }; |
267 | |
268 | static CaptureState CombineCaptureState(CaptureState aFirst, |
269 | CaptureState aSecond) { |
270 | if (aFirst == CaptureState::Enabled || aSecond == CaptureState::Enabled) { |
271 | return CaptureState::Enabled; |
272 | } |
273 | if (aFirst == CaptureState::Disabled || aSecond == CaptureState::Disabled) { |
274 | return CaptureState::Disabled; |
275 | } |
276 | MOZ_ASSERT(aFirst == CaptureState::Off)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aFirst == CaptureState::Off)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aFirst == CaptureState::Off) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aFirst == CaptureState::Off" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFirst == CaptureState::Off" ")"); do { *((volatile int*)__null) = 276; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
277 | MOZ_ASSERT(aSecond == CaptureState::Off)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSecond == CaptureState::Off)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aSecond == CaptureState::Off ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aSecond == CaptureState::Off", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSecond == CaptureState::Off" ")"); do { *((volatile int*)__null) = 277; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
278 | return CaptureState::Off; |
279 | } |
280 | |
281 | static uint16_t FromCaptureState(CaptureState aState) { |
282 | MOZ_ASSERT(aState == CaptureState::Off || aState == CaptureState::Enabled ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aState == CaptureState::Off || aState == CaptureState ::Enabled || aState == CaptureState::Disabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled" ")"); do { *((volatile int*)__null) = 283; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
283 | aState == CaptureState::Disabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aState == CaptureState::Off || aState == CaptureState ::Enabled || aState == CaptureState::Disabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState == CaptureState::Off || aState == CaptureState::Enabled || aState == CaptureState::Disabled" ")"); do { *((volatile int*)__null) = 283; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
284 | return static_cast<uint16_t>(aState); |
285 | } |
286 | |
287 | void MediaManager::CallOnError(GetUserMediaErrorCallback& aCallback, |
288 | MediaStreamError& aError) { |
289 | aCallback.Call(aError); |
290 | } |
291 | |
292 | void MediaManager::CallOnSuccess(GetUserMediaSuccessCallback& aCallback, |
293 | DOMMediaStream& aStream) { |
294 | aCallback.Call(aStream); |
295 | } |
296 | |
297 | enum class PersistentPermissionState : uint32_t { |
298 | Unknown = nsIPermissionManager::UNKNOWN_ACTION, |
299 | Allow = nsIPermissionManager::ALLOW_ACTION, |
300 | Deny = nsIPermissionManager::DENY_ACTION, |
301 | Prompt = nsIPermissionManager::PROMPT_ACTION, |
302 | }; |
303 | |
304 | static PersistentPermissionState CheckPermission( |
305 | PersistentPermissionState aPermission) { |
306 | switch (aPermission) { |
307 | case PersistentPermissionState::Unknown: |
308 | case PersistentPermissionState::Allow: |
309 | case PersistentPermissionState::Deny: |
310 | case PersistentPermissionState::Prompt: |
311 | return aPermission; |
312 | } |
313 | MOZ_CRASH("Unexpected permission value")do { do { } while (false); MOZ_ReportCrash("" "Unexpected permission value" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 313); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected permission value" ")"); do { *((volatile int*)__null) = 313; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
314 | } |
315 | |
316 | struct WindowPersistentPermissionState { |
317 | PersistentPermissionState mCameraPermission; |
318 | PersistentPermissionState mMicrophonePermission; |
319 | }; |
320 | |
321 | static Result<WindowPersistentPermissionState, nsresult> |
322 | GetPersistentPermissions(uint64_t aWindowId) { |
323 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowId); |
324 | if (NS_WARN_IF(!window)NS_warn_if_impl(!window, "!window", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 324) || NS_WARN_IF(!window->GetPrincipal())NS_warn_if_impl(!window->GetPrincipal(), "!window->GetPrincipal()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 324)) { |
325 | return Err(NS_ERROR_INVALID_ARG); |
326 | } |
327 | |
328 | Document* doc = window->GetExtantDoc(); |
329 | if (NS_WARN_IF(!doc)NS_warn_if_impl(!doc, "!doc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 329)) { |
330 | return Err(NS_ERROR_INVALID_ARG); |
331 | } |
332 | |
333 | nsIPrincipal* principal = window->GetPrincipal(); |
334 | if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 334)) { |
335 | return Err(NS_ERROR_INVALID_ARG); |
336 | } |
337 | |
338 | nsresult rv; |
339 | RefPtr<PermissionDelegateHandler> permDelegate = |
340 | doc->GetPermissionDelegateHandler(); |
341 | if (NS_WARN_IF(!permDelegate)NS_warn_if_impl(!permDelegate, "!permDelegate", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 341)) { |
342 | return Err(NS_ERROR_INVALID_ARG); |
343 | } |
344 | |
345 | uint32_t audio = nsIPermissionManager::UNKNOWN_ACTION; |
346 | uint32_t video = nsIPermissionManager::UNKNOWN_ACTION; |
347 | { |
348 | rv = permDelegate->GetPermission("microphone"_ns, &audio, true); |
349 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 349)) { |
350 | return Err(rv); |
351 | } |
352 | rv = permDelegate->GetPermission("camera"_ns, &video, true); |
353 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 353)) { |
354 | return Err(rv); |
355 | } |
356 | } |
357 | |
358 | return WindowPersistentPermissionState{ |
359 | CheckPermission(static_cast<PersistentPermissionState>(video)), |
360 | CheckPermission(static_cast<PersistentPermissionState>(audio))}; |
361 | } |
362 | |
363 | /** |
364 | * DeviceListener has threadsafe refcounting for use across the main, media and |
365 | * MTG threads. But it has a non-threadsafe SupportsWeakPtr for WeakPtr usage |
366 | * only from main thread, to ensure that garbage- and cycle-collected objects |
367 | * don't hold a reference to it during late shutdown. |
368 | */ |
369 | class DeviceListener : public SupportsWeakPtr { |
370 | public: |
371 | typedef MozPromise<bool /* aIgnored */, RefPtr<MediaMgrError>, true> |
372 | DeviceListenerPromise; |
373 | |
374 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<DeviceListener>, "Reference-counted class " "DeviceListener" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 375; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("DeviceListener"), (uint32_t)(sizeof(*this))); return (nsrefcnt)count; } MozExternalRefCountType Release(void) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 375 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("DeviceListener")); if (count == 0) { ::mozilla::detail ::ProxyDeleteVoid( "ProxyDelete " "DeviceListener", ::mozilla ::GetMainThreadSerialEventTarget(), this, [](void* self) { delete static_cast<DeviceListener*>(self); }); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type; protected : ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
375 | DeviceListener)public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<DeviceListener>, "Reference-counted class " "DeviceListener" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 375; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("DeviceListener"), (uint32_t)(sizeof(*this))); return (nsrefcnt)count; } MozExternalRefCountType Release(void) { do { static_assert( mozilla::detail::AssertionConditionType< decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 375 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("DeviceListener")); if (count == 0) { ::mozilla::detail ::ProxyDeleteVoid( "ProxyDelete " "DeviceListener", ::mozilla ::GetMainThreadSerialEventTarget(), this, [](void* self) { delete static_cast<DeviceListener*>(self); }); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type; protected : ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
376 | |
377 | DeviceListener(); |
378 | |
379 | /** |
380 | * Registers this device listener as belonging to the given window listener. |
381 | * Stop() must be called on registered DeviceListeners before destruction. |
382 | */ |
383 | void Register(GetUserMediaWindowListener* aListener); |
384 | |
385 | /** |
386 | * Marks this listener as active and creates the internal device state. |
387 | */ |
388 | void Activate(RefPtr<LocalMediaDevice> aDevice, |
389 | RefPtr<LocalTrackSource> aTrackSource, bool aStartMuted); |
390 | |
391 | /** |
392 | * Posts a task to initialize and start the associated device. |
393 | */ |
394 | RefPtr<DeviceListenerPromise> InitializeAsync(); |
395 | |
396 | /** |
397 | * Posts a task to stop the device associated with this DeviceListener and |
398 | * notifies the associated window listener that a track was stopped. |
399 | * |
400 | * This will also clean up the weak reference to the associated window |
401 | * listener, and tell the window listener to remove its hard reference to this |
402 | * DeviceListener, so any caller will need to keep its own hard ref. |
403 | */ |
404 | void Stop(); |
405 | |
406 | /** |
407 | * Gets the main thread MediaTrackSettings from the MediaEngineSource |
408 | * associated with aTrack. |
409 | */ |
410 | void GetSettings(MediaTrackSettings& aOutSettings) const; |
411 | |
412 | /** |
413 | * Posts a task to set the enabled state of the device associated with this |
414 | * DeviceListener to aEnabled and notifies the associated window listener that |
415 | * a track's state has changed. |
416 | * |
417 | * Turning the hardware off while the device is disabled is supported for: |
418 | * - Camera (enabled by default, controlled by pref |
419 | * "media.getusermedia.camera.off_while_disabled.enabled") |
420 | * - Microphone (disabled by default, controlled by pref |
421 | * "media.getusermedia.microphone.off_while_disabled.enabled") |
422 | * Screen-, app-, or windowsharing is not supported at this time. |
423 | * |
424 | * The behavior is also different between disabling and enabling a device. |
425 | * While enabling is immediate, disabling only happens after a delay. |
426 | * This is now defaulting to 3 seconds but can be overriden by prefs: |
427 | * - "media.getusermedia.camera.off_while_disabled.delay_ms" and |
428 | * - "media.getusermedia.microphone.off_while_disabled.delay_ms". |
429 | * |
430 | * The delay is in place to prevent misuse by malicious sites. If a track is |
431 | * re-enabled before the delay has passed, the device will not be touched |
432 | * until another disable followed by the full delay happens. |
433 | */ |
434 | void SetDeviceEnabled(bool aEnabled); |
435 | |
436 | /** |
437 | * Posts a task to set the muted state of the device associated with this |
438 | * DeviceListener to aMuted and notifies the associated window listener that a |
439 | * track's state has changed. |
440 | * |
441 | * Turning the hardware off while the device is muted is supported for: |
442 | * - Camera (enabled by default, controlled by pref |
443 | * "media.getusermedia.camera.off_while_disabled.enabled") |
444 | * - Microphone (disabled by default, controlled by pref |
445 | * "media.getusermedia.microphone.off_while_disabled.enabled") |
446 | * Screen-, app-, or windowsharing is not supported at this time. |
447 | */ |
448 | void SetDeviceMuted(bool aMuted); |
449 | |
450 | /** |
451 | * Mutes or unmutes the associated video device if it is a camera. |
452 | */ |
453 | void MuteOrUnmuteCamera(bool aMute); |
454 | void MuteOrUnmuteMicrophone(bool aMute); |
455 | |
456 | LocalMediaDevice* GetDevice() const { |
457 | return mDeviceState ? mDeviceState->mDevice.get() : nullptr; |
458 | } |
459 | |
460 | bool Activated() const { return static_cast<bool>(mDeviceState); } |
461 | |
462 | bool Stopped() const { return mStopped; } |
463 | |
464 | bool CapturingVideo() const; |
465 | |
466 | bool CapturingAudio() const; |
467 | |
468 | CaptureState CapturingSource(MediaSourceEnum aSource) const; |
469 | |
470 | RefPtr<DeviceListenerPromise> ApplyConstraints( |
471 | const MediaTrackConstraints& aConstraints, CallerType aCallerType); |
472 | |
473 | PrincipalHandle GetPrincipalHandle() const; |
474 | |
475 | size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { |
476 | size_t amount = aMallocSizeOf(this); |
477 | // Assume mPrincipalHandle refers to a principal owned elsewhere. |
478 | // DeviceState does not have support for memory accounting. |
479 | return amount; |
480 | } |
481 | |
482 | private: |
483 | virtual ~DeviceListener() { |
484 | MOZ_ASSERT(mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mStopped", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mStopped" ")" ); do { *((volatile int*)__null) = 484; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
485 | MOZ_ASSERT(!mWindowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mWindowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mWindowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mWindowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mWindowListener" ")"); do { *((volatile int*)__null) = 485; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
486 | } |
487 | |
488 | using DeviceOperationPromise = |
489 | MozPromise<nsresult, bool, /* IsExclusive = */ true>; |
490 | |
491 | /** |
492 | * Posts a task to start or stop the device associated with aTrack, based on |
493 | * a passed-in boolean. Private method used by SetDeviceEnabled and |
494 | * SetDeviceMuted. |
495 | */ |
496 | RefPtr<DeviceOperationPromise> UpdateDevice(bool aOn); |
497 | |
498 | // true after this listener has had all devices stopped. MainThread only. |
499 | bool mStopped; |
500 | |
501 | // never ever indirect off this; just for assertions |
502 | PRThread* mMainThreadCheck; |
503 | |
504 | // Set in Register() on main thread, then read from any thread. |
505 | PrincipalHandle mPrincipalHandle; |
506 | |
507 | // Weak pointer to the window listener that owns us. MainThread only. |
508 | GetUserMediaWindowListener* mWindowListener; |
509 | |
510 | // Accessed from MediaTrackGraph thread, MediaManager thread, and MainThread |
511 | // No locking needed as it's set on Activate() and never assigned to again. |
512 | UniquePtr<DeviceState> mDeviceState; |
513 | |
514 | MediaEventListener mCaptureEndedListener; |
515 | }; |
516 | |
517 | /** |
518 | * This class represents a WindowID and handles all MediaTrackListeners |
519 | * (here subclassed as DeviceListeners) used to feed GetUserMedia tracks. |
520 | * It proxies feedback from them into messages for browser chrome. |
521 | * The DeviceListeners are used to Start() and Stop() the underlying |
522 | * MediaEngineSource when MediaStreams are assigned and deassigned in content. |
523 | */ |
524 | class GetUserMediaWindowListener { |
525 | friend MediaManager; |
526 | |
527 | public: |
528 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GetUserMediaWindowListener)public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<GetUserMediaWindowListener>, "Reference-counted class " "GetUserMediaWindowListener" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 528; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("GetUserMediaWindowListener"), (uint32_t)(sizeof (*this))); return (nsrefcnt)count; } MozExternalRefCountType Release (void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 528 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("GetUserMediaWindowListener")); if (count == 0) { delete (this); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
529 | |
530 | // Create in an inactive state |
531 | GetUserMediaWindowListener(uint64_t aWindowID, |
532 | const PrincipalHandle& aPrincipalHandle) |
533 | : mWindowID(aWindowID), |
534 | mPrincipalHandle(aPrincipalHandle), |
535 | mChromeNotificationTaskPosted(false) {} |
536 | |
537 | /** |
538 | * Registers an inactive gUM device listener for this WindowListener. |
539 | */ |
540 | void Register(RefPtr<DeviceListener> aListener) { |
541 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 541; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
542 | MOZ_ASSERT(aListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aListener", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 542); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aListener" ")" ); do { *((volatile int*)__null) = 542; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
543 | MOZ_ASSERT(!aListener->Activated())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aListener->Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aListener->Activated())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aListener->Activated()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aListener->Activated()" ")"); do { *((volatile int*)__null) = 543; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
544 | MOZ_ASSERT(!mInactiveListeners.Contains(aListener), "Already registered")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)" " (" "Already registered" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 544); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)" ") (" "Already registered" ")"); do { *((volatile int*)__null ) = 544; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
545 | MOZ_ASSERT(!mActiveListeners.Contains(aListener), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "Already activated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "Already activated" ")"); do { *((volatile int*)__null ) = 545; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
546 | |
547 | aListener->Register(this); |
548 | mInactiveListeners.AppendElement(std::move(aListener)); |
549 | } |
550 | |
551 | /** |
552 | * Activates an already registered and inactive gUM device listener for this |
553 | * WindowListener. |
554 | */ |
555 | void Activate(RefPtr<DeviceListener> aListener, |
556 | RefPtr<LocalMediaDevice> aDevice, |
557 | RefPtr<LocalTrackSource> aTrackSource) { |
558 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 558; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
559 | MOZ_ASSERT(aListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aListener", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aListener" ")" ); do { *((volatile int*)__null) = 559; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
560 | MOZ_ASSERT(!aListener->Activated())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aListener->Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aListener->Activated())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aListener->Activated()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 560); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aListener->Activated()" ")"); do { *((volatile int*)__null) = 560; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
561 | MOZ_ASSERT(mInactiveListeners.Contains(aListener),do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mInactiveListeners.Contains(aListener)" " (" "Must be registered to activate" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Contains(aListener)" ") (" "Must be registered to activate" ")"); do { *((volatile int*)__null) = 562; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
562 | "Must be registered to activate")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mInactiveListeners.Contains(aListener)" " (" "Must be registered to activate" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Contains(aListener)" ") (" "Must be registered to activate" ")"); do { *((volatile int*)__null) = 562; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
563 | MOZ_ASSERT(!mActiveListeners.Contains(aListener), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "Already activated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "Already activated" ")"); do { *((volatile int*)__null ) = 563; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
564 | |
565 | bool muted = false; |
566 | if (aDevice->Kind() == MediaDeviceKind::Videoinput) { |
567 | muted = mCamerasAreMuted; |
568 | } else if (aDevice->Kind() == MediaDeviceKind::Audioinput) { |
569 | muted = mMicrophonesAreMuted; |
570 | } else { |
571 | MOZ_CRASH("Unexpected device kind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected device kind" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 571); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected device kind" ")"); do { *((volatile int*)__null) = 571; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
572 | } |
573 | |
574 | mInactiveListeners.RemoveElement(aListener); |
575 | aListener->Activate(std::move(aDevice), std::move(aTrackSource), muted); |
576 | mActiveListeners.AppendElement(std::move(aListener)); |
577 | } |
578 | |
579 | /** |
580 | * Removes all DeviceListeners from this window listener. |
581 | * Removes this window listener from the list of active windows, so callers |
582 | * need to make sure to hold a strong reference. |
583 | */ |
584 | void RemoveAll() { |
585 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 585; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
586 | |
587 | for (auto& l : mInactiveListeners.Clone()) { |
588 | Remove(l); |
589 | } |
590 | for (auto& l : mActiveListeners.Clone()) { |
591 | Remove(l); |
592 | } |
593 | MOZ_ASSERT(mInactiveListeners.Length() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInactiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInactiveListeners.Length() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Length() == 0" ")"); do { *((volatile int*)__null) = 593; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
594 | MOZ_ASSERT(mActiveListeners.Length() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mActiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mActiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mActiveListeners.Length() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 594); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActiveListeners.Length() == 0" ")"); do { *((volatile int*)__null) = 594; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
595 | |
596 | MediaManager* mgr = MediaManager::GetIfExists(); |
597 | if (!mgr) { |
598 | MOZ_ASSERT(false, "MediaManager should stay until everything is removed")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MediaManager should stay until everything is removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MediaManager should stay until everything is removed" ")"); do { *((volatile int*)__null) = 598; __attribute__((nomerge) ) ::abort(); } while (false); } } while (false); |
599 | return; |
600 | } |
601 | GetUserMediaWindowListener* windowListener = |
602 | mgr->GetWindowListener(mWindowID); |
603 | |
604 | if (!windowListener) { |
605 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
606 | auto* globalWindow = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID); |
607 | if (globalWindow) { |
608 | auto req = MakeRefPtr<GetUserMediaRequest>( |
609 | globalWindow, VoidString(), VoidString(), |
610 | UserActivation::IsHandlingUserInput()); |
611 | obs->NotifyWhenScriptSafe(req, "recording-device-stopped", nullptr); |
612 | } |
613 | return; |
614 | } |
615 | |
616 | MOZ_ASSERT(windowListener == this,do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowListener == this)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowListener == this))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener == this" " (" "There should only be one window listener per window ID" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener == this" ") (" "There should only be one window listener per window ID" ")"); do { *((volatile int*)__null) = 617; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
617 | "There should only be one window listener per window ID")do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowListener == this)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowListener == this))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener == this" " (" "There should only be one window listener per window ID" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener == this" ") (" "There should only be one window listener per window ID" ")"); do { *((volatile int*)__null) = 617; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
618 | |
619 | LOG("GUMWindowListener %p removing windowID %" PRIu64"l" "u", this, mWindowID); |
620 | mgr->RemoveWindowID(mWindowID); |
621 | } |
622 | |
623 | /** |
624 | * Removes a listener from our lists. Safe to call without holding a hard |
625 | * reference. That said, you'll still want to iterate on a copy of said lists, |
626 | * if you end up calling this method (or methods that may call this method) in |
627 | * the loop, to avoid inadvertently skipping members. |
628 | * |
629 | * For use only from GetUserMediaWindowListener and DeviceListener. |
630 | */ |
631 | bool Remove(RefPtr<DeviceListener> aListener) { |
632 | // We refcount aListener on entry since we're going to proxy-release it |
633 | // below to prevent the refcount going to zero on callers who might be |
634 | // inside the listener, but operating without a hard reference to self. |
635 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 635; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
636 | |
637 | if (!mInactiveListeners.RemoveElement(aListener) && |
638 | !mActiveListeners.RemoveElement(aListener)) { |
639 | return false; |
640 | } |
641 | MOZ_ASSERT(!mInactiveListeners.Contains(aListener),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 643; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
642 | "A DeviceListener should only be once in one of "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 643; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
643 | "mInactiveListeners and mActiveListeners")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInactiveListeners.Contains(aListener))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!mInactiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInactiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInactiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 643; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
644 | MOZ_ASSERT(!mActiveListeners.Contains(aListener),do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 646; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
645 | "A DeviceListener should only be once in one of "do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 646; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
646 | "mInactiveListeners and mActiveListeners")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mActiveListeners.Contains(aListener))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(!mActiveListeners.Contains(aListener)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mActiveListeners.Contains(aListener)" " (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActiveListeners.Contains(aListener)" ") (" "A DeviceListener should only be once in one of " "mInactiveListeners and mActiveListeners" ")"); do { *((volatile int*)__null) = 646; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
647 | |
648 | LOG("GUMWindowListener %p stopping DeviceListener %p.", this, |
649 | aListener.get()); |
650 | aListener->Stop(); |
651 | |
652 | if (LocalMediaDevice* removedDevice = aListener->GetDevice()) { |
653 | bool revokePermission = true; |
654 | nsString removedRawId; |
655 | nsString removedSourceType; |
656 | removedDevice->GetRawId(removedRawId); |
657 | removedDevice->GetMediaSource(removedSourceType); |
658 | |
659 | for (const auto& l : mActiveListeners) { |
660 | if (LocalMediaDevice* device = l->GetDevice()) { |
661 | nsString rawId; |
662 | device->GetRawId(rawId); |
663 | if (removedRawId.Equals(rawId)) { |
664 | revokePermission = false; |
665 | break; |
666 | } |
667 | } |
668 | } |
669 | |
670 | if (revokePermission) { |
671 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
672 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID); |
673 | auto req = MakeRefPtr<GetUserMediaRequest>( |
674 | window, removedRawId, removedSourceType, |
675 | UserActivation::IsHandlingUserInput()); |
676 | obs->NotifyWhenScriptSafe(req, "recording-device-stopped", nullptr); |
677 | } |
678 | } |
679 | |
680 | if (mInactiveListeners.Length() == 0 && mActiveListeners.Length() == 0) { |
681 | LOG("GUMWindowListener %p Removed last DeviceListener. Cleaning up.", |
682 | this); |
683 | RemoveAll(); |
684 | } |
685 | |
686 | nsCOMPtr<nsIEventTarget> mainTarget = do_GetMainThread(); |
687 | // To allow being invoked by callers not holding a strong reference to self, |
688 | // hold the listener alive until the stack has unwound, by always |
689 | // dispatching a runnable (aAlwaysProxy = true) |
690 | NS_ProxyRelease(__func__, mainTarget, aListener.forget(), true); |
691 | return true; |
692 | } |
693 | |
694 | /** |
695 | * Stops all screen/window/audioCapture sharing, but not camera or microphone. |
696 | */ |
697 | void StopSharing(); |
698 | |
699 | void StopRawID(const nsString& removedDeviceID); |
700 | |
701 | void MuteOrUnmuteCameras(bool aMute); |
702 | void MuteOrUnmuteMicrophones(bool aMute); |
703 | |
704 | /** |
705 | * Called by one of our DeviceListeners when one of its tracks has changed so |
706 | * that chrome state is affected. |
707 | * Schedules an event for the next stable state to update chrome. |
708 | */ |
709 | void ChromeAffectingStateChanged(); |
710 | |
711 | /** |
712 | * Called in stable state to send a notification to update chrome. |
713 | */ |
714 | void NotifyChrome(); |
715 | |
716 | bool CapturingVideo() const { |
717 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 717; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
718 | for (auto& l : mActiveListeners) { |
719 | if (l->CapturingVideo()) { |
720 | return true; |
721 | } |
722 | } |
723 | return false; |
724 | } |
725 | |
726 | bool CapturingAudio() const { |
727 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 727); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 727; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
728 | for (auto& l : mActiveListeners) { |
729 | if (l->CapturingAudio()) { |
730 | return true; |
731 | } |
732 | } |
733 | return false; |
734 | } |
735 | |
736 | CaptureState CapturingSource(MediaSourceEnum aSource) const { |
737 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 737); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 737; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
738 | CaptureState result = CaptureState::Off; |
739 | for (auto& l : mActiveListeners) { |
740 | result = CombineCaptureState(result, l->CapturingSource(aSource)); |
741 | } |
742 | return result; |
743 | } |
744 | |
745 | RefPtr<LocalMediaDeviceSetRefCnt> GetDevices() { |
746 | RefPtr devices = new LocalMediaDeviceSetRefCnt(); |
747 | for (auto& l : mActiveListeners) { |
748 | devices->AppendElement(l->GetDevice()); |
749 | } |
750 | return devices; |
751 | } |
752 | |
753 | uint64_t WindowID() const { return mWindowID; } |
754 | |
755 | PrincipalHandle GetPrincipalHandle() const { return mPrincipalHandle; } |
756 | |
757 | size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { |
758 | size_t amount = aMallocSizeOf(this); |
759 | // Assume mPrincipalHandle refers to a principal owned elsewhere. |
760 | amount += mInactiveListeners.ShallowSizeOfExcludingThis(aMallocSizeOf); |
761 | for (const RefPtr<DeviceListener>& listener : mInactiveListeners) { |
762 | amount += listener->SizeOfIncludingThis(aMallocSizeOf); |
763 | } |
764 | amount += mActiveListeners.ShallowSizeOfExcludingThis(aMallocSizeOf); |
765 | for (const RefPtr<DeviceListener>& listener : mActiveListeners) { |
766 | amount += listener->SizeOfIncludingThis(aMallocSizeOf); |
767 | } |
768 | return amount; |
769 | } |
770 | |
771 | private: |
772 | ~GetUserMediaWindowListener() { |
773 | MOZ_ASSERT(mInactiveListeners.Length() == 0,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInactiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInactiveListeners.Length() == 0" " (" "Inactive listeners should already be removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Length() == 0" ") (" "Inactive listeners should already be removed" ")"); do { *((volatile int*)__null) = 774; __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
774 | "Inactive listeners should already be removed")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInactiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInactiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInactiveListeners.Length() == 0" " (" "Inactive listeners should already be removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInactiveListeners.Length() == 0" ") (" "Inactive listeners should already be removed" ")"); do { *((volatile int*)__null) = 774; __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
775 | MOZ_ASSERT(mActiveListeners.Length() == 0,do { static_assert( mozilla::detail::AssertionConditionType< decltype(mActiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mActiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mActiveListeners.Length() == 0" " (" "Active listeners should already be removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActiveListeners.Length() == 0" ") (" "Active listeners should already be removed" ")"); do { *((volatile int*)__null) = 776; __attribute__((nomerge)) ::abort (); } while (false); } } while (false) |
776 | "Active listeners should already be removed")do { static_assert( mozilla::detail::AssertionConditionType< decltype(mActiveListeners.Length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mActiveListeners.Length() == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mActiveListeners.Length() == 0" " (" "Active listeners should already be removed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mActiveListeners.Length() == 0" ") (" "Active listeners should already be removed" ")"); do { *((volatile int*)__null) = 776; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
777 | } |
778 | |
779 | uint64_t mWindowID; |
780 | const PrincipalHandle mPrincipalHandle; |
781 | |
782 | // true if we have scheduled a task to notify chrome in the next stable state. |
783 | // The task will reset this to false. MainThread only. |
784 | bool mChromeNotificationTaskPosted; |
785 | |
786 | nsTArray<RefPtr<DeviceListener>> mInactiveListeners; |
787 | nsTArray<RefPtr<DeviceListener>> mActiveListeners; |
788 | |
789 | // Whether camera and microphone access in this window are currently |
790 | // User Agent (UA) muted. When true, new and cloned tracks must start |
791 | // out muted, to avoid JS circumventing UA mute. Per-camera and |
792 | // per-microphone UA muting is not supported. |
793 | bool mCamerasAreMuted = false; |
794 | bool mMicrophonesAreMuted = false; |
795 | }; |
796 | |
797 | class LocalTrackSource : public MediaStreamTrackSource { |
798 | public: |
799 | LocalTrackSource(nsIPrincipal* aPrincipal, const nsString& aLabel, |
800 | const RefPtr<DeviceListener>& aListener, |
801 | MediaSourceEnum aSource, MediaTrack* aTrack, |
802 | RefPtr<PeerIdentity> aPeerIdentity, |
803 | TrackingId aTrackingId = TrackingId()) |
804 | : MediaStreamTrackSource(aPrincipal, aLabel, std::move(aTrackingId)), |
805 | mSource(aSource), |
806 | mTrack(aTrack), |
807 | mPeerIdentity(std::move(aPeerIdentity)), |
808 | mListener(aListener.get()) {} |
809 | |
810 | MediaSourceEnum GetMediaSource() const override { return mSource; } |
811 | |
812 | const PeerIdentity* GetPeerIdentity() const override { return mPeerIdentity; } |
813 | |
814 | RefPtr<MediaStreamTrackSource::ApplyConstraintsPromise> ApplyConstraints( |
815 | const MediaTrackConstraints& aConstraints, |
816 | CallerType aCallerType) override { |
817 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 817; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
818 | if (sHasMainThreadShutdown || !mListener) { |
819 | // Track has been stopped, or we are in shutdown. In either case |
820 | // there's no observable outcome, so pretend we succeeded. |
821 | return MediaStreamTrackSource::ApplyConstraintsPromise::CreateAndResolve( |
822 | false, __func__); |
823 | } |
824 | return mListener->ApplyConstraints(aConstraints, aCallerType); |
825 | } |
826 | |
827 | void GetSettings(MediaTrackSettings& aOutSettings) override { |
828 | if (mListener) { |
829 | mListener->GetSettings(aOutSettings); |
830 | } |
831 | } |
832 | |
833 | void Stop() override { |
834 | if (mListener) { |
835 | mListener->Stop(); |
836 | mListener = nullptr; |
837 | } |
838 | if (!mTrack->IsDestroyed()) { |
839 | mTrack->Destroy(); |
840 | } |
841 | } |
842 | |
843 | void Disable() override { |
844 | if (mListener) { |
845 | mListener->SetDeviceEnabled(false); |
846 | } |
847 | } |
848 | |
849 | void Enable() override { |
850 | if (mListener) { |
851 | mListener->SetDeviceEnabled(true); |
852 | } |
853 | } |
854 | |
855 | void Mute() { |
856 | MutedChanged(true); |
857 | mTrack->SetDisabledTrackMode(DisabledTrackMode::SILENCE_BLACK); |
858 | } |
859 | |
860 | void Unmute() { |
861 | MutedChanged(false); |
862 | mTrack->SetDisabledTrackMode(DisabledTrackMode::ENABLED); |
863 | } |
864 | |
865 | const MediaSourceEnum mSource; |
866 | const RefPtr<MediaTrack> mTrack; |
867 | const RefPtr<const PeerIdentity> mPeerIdentity; |
868 | |
869 | protected: |
870 | ~LocalTrackSource() { |
871 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 871); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 871; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
872 | MOZ_ASSERT(mTrack->IsDestroyed())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mTrack->IsDestroyed())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mTrack->IsDestroyed()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mTrack->IsDestroyed()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 872); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTrack->IsDestroyed()" ")"); do { *((volatile int*)__null) = 872; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
873 | } |
874 | |
875 | // This is a weak pointer to avoid having the DeviceListener (which may |
876 | // have references to threads and threadpools) kept alive by DOM-objects |
877 | // that may have ref-cycles and thus are released very late during |
878 | // shutdown, even after xpcom-shutdown-threads. See bug 1351655 for what |
879 | // can happen. |
880 | WeakPtr<DeviceListener> mListener; |
881 | }; |
882 | |
883 | class AudioCaptureTrackSource : public LocalTrackSource { |
884 | public: |
885 | AudioCaptureTrackSource(nsIPrincipal* aPrincipal, nsPIDOMWindowInner* aWindow, |
886 | const nsString& aLabel, |
887 | AudioCaptureTrack* aAudioCaptureTrack, |
888 | RefPtr<PeerIdentity> aPeerIdentity) |
889 | : LocalTrackSource(aPrincipal, aLabel, nullptr, |
890 | MediaSourceEnum::AudioCapture, aAudioCaptureTrack, |
891 | std::move(aPeerIdentity)), |
892 | mWindow(aWindow), |
893 | mAudioCaptureTrack(aAudioCaptureTrack) { |
894 | mAudioCaptureTrack->Start(); |
895 | mAudioCaptureTrack->Graph()->RegisterCaptureTrackForWindow( |
896 | mWindow->WindowID(), mAudioCaptureTrack); |
897 | mWindow->SetAudioCapture(true); |
898 | } |
899 | |
900 | void Stop() override { |
901 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 901); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 901; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
902 | if (!mAudioCaptureTrack->IsDestroyed()) { |
903 | MOZ_ASSERT(mWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWindow" ")" ); do { *((volatile int*)__null) = 903; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
904 | mWindow->SetAudioCapture(false); |
905 | mAudioCaptureTrack->Graph()->UnregisterCaptureTrackForWindow( |
906 | mWindow->WindowID()); |
907 | mWindow = nullptr; |
908 | } |
909 | // LocalTrackSource destroys the track. |
910 | LocalTrackSource::Stop(); |
911 | MOZ_ASSERT(mAudioCaptureTrack->IsDestroyed())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mAudioCaptureTrack->IsDestroyed())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mAudioCaptureTrack->IsDestroyed ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mAudioCaptureTrack->IsDestroyed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudioCaptureTrack->IsDestroyed()" ")"); do { *((volatile int*)__null) = 911; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
912 | } |
913 | |
914 | ProcessedMediaTrack* InputTrack() const { return mAudioCaptureTrack.get(); } |
915 | |
916 | protected: |
917 | ~AudioCaptureTrackSource() { |
918 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 918; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
919 | MOZ_ASSERT(mAudioCaptureTrack->IsDestroyed())do { static_assert( mozilla::detail::AssertionConditionType< decltype(mAudioCaptureTrack->IsDestroyed())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mAudioCaptureTrack->IsDestroyed ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mAudioCaptureTrack->IsDestroyed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 919); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudioCaptureTrack->IsDestroyed()" ")"); do { *((volatile int*)__null) = 919; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
920 | } |
921 | |
922 | RefPtr<nsPIDOMWindowInner> mWindow; |
923 | const RefPtr<AudioCaptureTrack> mAudioCaptureTrack; |
924 | }; |
925 | |
926 | /** |
927 | * nsIMediaDevice implementation. |
928 | */ |
929 | 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" , 929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 929; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("LocalMediaDevice" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("LocalMediaDevice" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"LocalMediaDevice\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"LocalMediaDevice\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 929; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("LocalMediaDevice" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("LocalMediaDevice" ), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType LocalMediaDevice::Release(void) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 929 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("LocalMediaDevice" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("LocalMediaDevice" != nullptr ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "\"LocalMediaDevice\" != nullptr" " (" "Must specify a name" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 929); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"LocalMediaDevice\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 929; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("LocalMediaDevice" " not thread-safe"); const char* const nametmp = "LocalMediaDevice"; nsrefcnt count = -- mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count ; } nsresult LocalMediaDevice::QueryInterface(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak (NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 929); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<LocalMediaDevice, nsIMediaDevice>, int32_t ( reinterpret_cast<char*>(static_cast<nsIMediaDevice *>((LocalMediaDevice*)0x1000)) - reinterpret_cast<char* >((LocalMediaDevice*)0x1000))}, {&mozilla::detail::kImplementedIID <LocalMediaDevice, nsISupports>, int32_t(reinterpret_cast <char*>(static_cast<nsISupports*>( static_cast< nsIMediaDevice*>((LocalMediaDevice*)0x1000))) - reinterpret_cast <char*>((LocalMediaDevice*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface" ); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID , aInstancePtr, table); return rv; } |
930 | |
931 | MediaDevice::MediaDevice(MediaEngine* aEngine, MediaSourceEnum aMediaSource, |
932 | const nsString& aRawName, const nsString& aRawID, |
933 | const nsString& aRawGroupID, IsScary aIsScary, |
934 | const OsPromptable canRequestOsLevelPrompt, |
935 | const IsPlaceholder aIsPlaceholder) |
936 | : mEngine(aEngine), |
937 | mAudioDeviceInfo(nullptr), |
938 | mMediaSource(aMediaSource), |
939 | mKind(MediaEngineSource::IsVideo(aMediaSource) |
940 | ? MediaDeviceKind::Videoinput |
941 | : MediaDeviceKind::Audioinput), |
942 | mScary(aIsScary == IsScary::Yes), |
943 | mCanRequestOsLevelPrompt(canRequestOsLevelPrompt == OsPromptable::Yes), |
944 | mIsFake(mEngine->IsFake()), |
945 | mIsPlaceholder(aIsPlaceholder == IsPlaceholder::Yes), |
946 | mType(NS_ConvertASCIItoUTF16(dom::GetEnumString(mKind))), |
947 | mRawID(aRawID), |
948 | mRawGroupID(aRawGroupID), |
949 | mRawName(aRawName) { |
950 | MOZ_ASSERT(mEngine)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mEngine)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mEngine))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mEngine", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mEngine" ")" ); do { *((volatile int*)__null) = 950; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
951 | } |
952 | |
953 | MediaDevice::MediaDevice(MediaEngine* aEngine, |
954 | const RefPtr<AudioDeviceInfo>& aAudioDeviceInfo, |
955 | const nsString& aRawID) |
956 | : mEngine(aEngine), |
957 | mAudioDeviceInfo(aAudioDeviceInfo), |
958 | mMediaSource(mAudioDeviceInfo->Type() == AudioDeviceInfo::TYPE_INPUT |
959 | ? MediaSourceEnum::Microphone |
960 | : MediaSourceEnum::Other), |
961 | mKind(mMediaSource == MediaSourceEnum::Microphone |
962 | ? MediaDeviceKind::Audioinput |
963 | : MediaDeviceKind::Audiooutput), |
964 | mScary(false), |
965 | mCanRequestOsLevelPrompt(false), |
966 | mIsFake(false), |
967 | mIsPlaceholder(false), |
968 | mType(NS_ConvertASCIItoUTF16(dom::GetEnumString(mKind))), |
969 | mRawID(aRawID), |
970 | mRawGroupID(mAudioDeviceInfo->GroupID()), |
971 | mRawName(mAudioDeviceInfo->Name()) {} |
972 | |
973 | /* static */ |
974 | RefPtr<MediaDevice> MediaDevice::CopyWithNewRawGroupId( |
975 | const RefPtr<MediaDevice>& aOther, const nsString& aRawGroupID) { |
976 | MOZ_ASSERT(!aOther->mAudioDeviceInfo, "device not supported")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aOther->mAudioDeviceInfo)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aOther->mAudioDeviceInfo ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!aOther->mAudioDeviceInfo" " (" "device not supported" ")" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOther->mAudioDeviceInfo" ") (" "device not supported" ")"); do { *((volatile int*)__null ) = 976; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
977 | return new MediaDevice(aOther->mEngine, aOther->mMediaSource, |
978 | aOther->mRawName, aOther->mRawID, aRawGroupID, |
979 | IsScary(aOther->mScary), |
980 | OsPromptable(aOther->mCanRequestOsLevelPrompt), |
981 | IsPlaceholder(aOther->mIsPlaceholder)); |
982 | } |
983 | |
984 | MediaDevice::~MediaDevice() = default; |
985 | |
986 | LocalMediaDevice::LocalMediaDevice(RefPtr<const MediaDevice> aRawDevice, |
987 | const nsString& aID, |
988 | const nsString& aGroupID, |
989 | const nsString& aName) |
990 | : mRawDevice(std::move(aRawDevice)), |
991 | mName(aName), |
992 | mID(aID), |
993 | mGroupID(aGroupID) { |
994 | MOZ_ASSERT(mRawDevice)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mRawDevice)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mRawDevice))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mRawDevice", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 994); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawDevice" ")" ); do { *((volatile int*)__null) = 994; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
995 | } |
996 | |
997 | /** |
998 | * Helper functions that implement the constraints algorithm from |
999 | * http://dev.w3.org/2011/webrtc/editor/getusermedia.html#methods-5 |
1000 | */ |
1001 | |
1002 | /* static */ |
1003 | bool LocalMediaDevice::StringsContain( |
1004 | const OwningStringOrStringSequence& aStrings, nsString aN) { |
1005 | return aStrings.IsString() ? aStrings.GetAsString() == aN |
1006 | : aStrings.GetAsStringSequence().Contains(aN); |
1007 | } |
1008 | |
1009 | /* static */ |
1010 | uint32_t LocalMediaDevice::FitnessDistance( |
1011 | nsString aN, const ConstrainDOMStringParameters& aParams) { |
1012 | if (aParams.mExact.WasPassed() && |
1013 | !StringsContain(aParams.mExact.Value(), aN)) { |
1014 | return UINT32_MAX(4294967295U); |
1015 | } |
1016 | if (aParams.mIdeal.WasPassed() && |
1017 | !StringsContain(aParams.mIdeal.Value(), aN)) { |
1018 | return 1; |
1019 | } |
1020 | return 0; |
1021 | } |
1022 | |
1023 | // Binding code doesn't templatize well... |
1024 | |
1025 | /* static */ |
1026 | uint32_t LocalMediaDevice::FitnessDistance( |
1027 | nsString aN, |
1028 | const OwningStringOrStringSequenceOrConstrainDOMStringParameters& |
1029 | aConstraint) { |
1030 | if (aConstraint.IsString()) { |
1031 | ConstrainDOMStringParameters params; |
1032 | params.mIdeal.Construct(); |
1033 | params.mIdeal.Value().SetAsString() = aConstraint.GetAsString(); |
1034 | return FitnessDistance(aN, params); |
1035 | } else if (aConstraint.IsStringSequence()) { |
1036 | ConstrainDOMStringParameters params; |
1037 | params.mIdeal.Construct(); |
1038 | params.mIdeal.Value().SetAsStringSequence() = |
1039 | aConstraint.GetAsStringSequence(); |
1040 | return FitnessDistance(aN, params); |
1041 | } else { |
1042 | return FitnessDistance(aN, aConstraint.GetAsConstrainDOMStringParameters()); |
1043 | } |
1044 | } |
1045 | |
1046 | uint32_t LocalMediaDevice::GetBestFitnessDistance( |
1047 | const nsTArray<const NormalizedConstraintSet*>& aConstraintSets, |
1048 | CallerType aCallerType) { |
1049 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1049); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1049; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1050 | MOZ_ASSERT(GetMediaSource() != MediaSourceEnum::Other)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetMediaSource() != MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(GetMediaSource() != MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("GetMediaSource() != MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetMediaSource() != MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 1050; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1051 | |
1052 | bool isChrome = aCallerType == CallerType::System; |
1053 | const nsString& id = isChrome ? RawID() : mID; |
1054 | auto type = GetMediaSource(); |
1055 | uint64_t distance = 0; |
1056 | if (!aConstraintSets.IsEmpty()) { |
1057 | if (isChrome /* For the screen/window sharing preview */ || |
1058 | type == MediaSourceEnum::Camera || |
1059 | type == MediaSourceEnum::Microphone) { |
1060 | distance += uint64_t(MediaConstraintsHelper::FitnessDistance( |
1061 | Some(id), aConstraintSets[0]->mDeviceId)) + |
1062 | uint64_t(MediaConstraintsHelper::FitnessDistance( |
1063 | Some(mGroupID), aConstraintSets[0]->mGroupId)); |
1064 | } |
1065 | } |
1066 | if (distance < UINT32_MAX(4294967295U)) { |
1067 | // Forward request to underlying object to interrogate per-mode |
1068 | // capabilities. |
1069 | distance += Source()->GetBestFitnessDistance(aConstraintSets); |
1070 | } |
1071 | return std::min<uint64_t>(distance, UINT32_MAX(4294967295U)); |
1072 | } |
1073 | |
1074 | NS_IMETHODIMPnsresult |
1075 | LocalMediaDevice::GetRawName(nsAString& aName) { |
1076 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1076; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1077 | aName.Assign(mRawDevice->mRawName); |
1078 | return NS_OK; |
1079 | } |
1080 | |
1081 | NS_IMETHODIMPnsresult |
1082 | LocalMediaDevice::GetType(nsAString& aType) { |
1083 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1083; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1084 | aType.Assign(mRawDevice->mType); |
1085 | return NS_OK; |
1086 | } |
1087 | |
1088 | NS_IMETHODIMPnsresult |
1089 | LocalMediaDevice::GetRawId(nsAString& aID) { |
1090 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1090; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1091 | aID.Assign(RawID()); |
1092 | return NS_OK; |
1093 | } |
1094 | |
1095 | NS_IMETHODIMPnsresult |
1096 | LocalMediaDevice::GetId(nsAString& aID) { |
1097 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1097); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1097; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1098 | aID.Assign(mID); |
1099 | return NS_OK; |
1100 | } |
1101 | |
1102 | NS_IMETHODIMPnsresult |
1103 | LocalMediaDevice::GetScary(bool* aScary) { |
1104 | *aScary = mRawDevice->mScary; |
1105 | return NS_OK; |
1106 | } |
1107 | |
1108 | NS_IMETHODIMPnsresult |
1109 | LocalMediaDevice::GetCanRequestOsLevelPrompt(bool* aCanRequestOsLevelPrompt) { |
1110 | *aCanRequestOsLevelPrompt = mRawDevice->mCanRequestOsLevelPrompt; |
1111 | return NS_OK; |
1112 | } |
1113 | |
1114 | void LocalMediaDevice::GetSettings(MediaTrackSettings& aOutSettings) { |
1115 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1115; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1116 | Source()->GetSettings(aOutSettings); |
1117 | } |
1118 | |
1119 | MediaEngineSource* LocalMediaDevice::Source() { |
1120 | if (!mSource) { |
1121 | mSource = mRawDevice->mEngine->CreateSource(mRawDevice); |
1122 | } |
1123 | return mSource; |
1124 | } |
1125 | |
1126 | const TrackingId& LocalMediaDevice::GetTrackingId() const { |
1127 | return mSource->GetTrackingId(); |
1128 | } |
1129 | |
1130 | // Threadsafe since mKind and mSource are const. |
1131 | NS_IMETHODIMPnsresult |
1132 | LocalMediaDevice::GetMediaSource(nsAString& aMediaSource) { |
1133 | if (Kind() == MediaDeviceKind::Audiooutput) { |
1134 | aMediaSource.Truncate(); |
1135 | } else { |
1136 | aMediaSource.AssignASCII(dom::GetEnumString(GetMediaSource())); |
1137 | } |
1138 | return NS_OK; |
1139 | } |
1140 | |
1141 | nsresult LocalMediaDevice::Allocate(const MediaTrackConstraints& aConstraints, |
1142 | const MediaEnginePrefs& aPrefs, |
1143 | uint64_t aWindowID, |
1144 | const char** aOutBadConstraint) { |
1145 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1145; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1146 | |
1147 | // Mock failure for automated tests. |
1148 | if (IsFake() && aConstraints.mDeviceId.WasPassed() && |
1149 | aConstraints.mDeviceId.Value().IsString() && |
1150 | aConstraints.mDeviceId.Value().GetAsString().EqualsASCII("bad device")) { |
1151 | return NS_ERROR_FAILURE; |
1152 | } |
1153 | |
1154 | return Source()->Allocate(aConstraints, aPrefs, aWindowID, aOutBadConstraint); |
1155 | } |
1156 | |
1157 | void LocalMediaDevice::SetTrack(const RefPtr<MediaTrack>& aTrack, |
1158 | const PrincipalHandle& aPrincipalHandle) { |
1159 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1159); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1159; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1160 | Source()->SetTrack(aTrack, aPrincipalHandle); |
1161 | } |
1162 | |
1163 | nsresult LocalMediaDevice::Start() { |
1164 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1164; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1165 | MOZ_ASSERT(Source())do { static_assert( mozilla::detail::AssertionConditionType< decltype(Source())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(Source()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("Source()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Source()" ")" ); do { *((volatile int*)__null) = 1165; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1166 | return Source()->Start(); |
1167 | } |
1168 | |
1169 | nsresult LocalMediaDevice::Reconfigure( |
1170 | const MediaTrackConstraints& aConstraints, const MediaEnginePrefs& aPrefs, |
1171 | const char** aOutBadConstraint) { |
1172 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1172; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1173 | auto type = GetMediaSource(); |
1174 | if (type == MediaSourceEnum::Camera || type == MediaSourceEnum::Microphone) { |
1175 | NormalizedConstraints c(aConstraints); |
1176 | if (MediaConstraintsHelper::FitnessDistance(Some(mID), c.mDeviceId) == |
1177 | UINT32_MAX(4294967295U)) { |
1178 | *aOutBadConstraint = "deviceId"; |
1179 | return NS_ERROR_INVALID_ARG; |
1180 | } |
1181 | if (MediaConstraintsHelper::FitnessDistance(Some(mGroupID), c.mGroupId) == |
1182 | UINT32_MAX(4294967295U)) { |
1183 | *aOutBadConstraint = "groupId"; |
1184 | return NS_ERROR_INVALID_ARG; |
1185 | } |
1186 | } |
1187 | return Source()->Reconfigure(aConstraints, aPrefs, aOutBadConstraint); |
1188 | } |
1189 | |
1190 | nsresult LocalMediaDevice::FocusOnSelectedSource() { |
1191 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1191; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1192 | return Source()->FocusOnSelectedSource(); |
1193 | } |
1194 | |
1195 | nsresult LocalMediaDevice::Stop() { |
1196 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1196); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1196; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1197 | MOZ_ASSERT(mSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mSource))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mSource", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1197); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSource" ")" ); do { *((volatile int*)__null) = 1197; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1198 | return mSource->Stop(); |
1199 | } |
1200 | |
1201 | nsresult LocalMediaDevice::Deallocate() { |
1202 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1202; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1203 | MOZ_ASSERT(mSource)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mSource)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mSource))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mSource", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSource" ")" ); do { *((volatile int*)__null) = 1203; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1204 | return mSource->Deallocate(); |
1205 | } |
1206 | |
1207 | MediaSourceEnum MediaDevice::GetMediaSource() const { return mMediaSource; } |
1208 | |
1209 | static const MediaTrackConstraints& GetInvariant( |
1210 | const OwningBooleanOrMediaTrackConstraints& aUnion) { |
1211 | static const MediaTrackConstraints empty; |
1212 | return aUnion.IsMediaTrackConstraints() ? aUnion.GetAsMediaTrackConstraints() |
1213 | : empty; |
1214 | } |
1215 | |
1216 | // Source getter returning full list |
1217 | |
1218 | static void GetMediaDevices(MediaEngine* aEngine, MediaSourceEnum aSrcType, |
1219 | MediaManager::MediaDeviceSet& aResult, |
1220 | const char* aMediaDeviceName = nullptr) { |
1221 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 1221; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1222 | |
1223 | LOG("%s: aEngine=%p, aSrcType=%" PRIu8"u" ", aMediaDeviceName=%s", __func__, |
1224 | aEngine, static_cast<uint8_t>(aSrcType), |
1225 | aMediaDeviceName ? aMediaDeviceName : "null"); |
1226 | nsTArray<RefPtr<MediaDevice>> devices; |
1227 | aEngine->EnumerateDevices(aSrcType, MediaSinkEnum::Other, &devices); |
1228 | |
1229 | /* |
1230 | * We're allowing multiple tabs to access the same camera for parity |
1231 | * with Chrome. See bug 811757 for some of the issues surrounding |
1232 | * this decision. To disallow, we'd filter by IsAvailable() as we used |
1233 | * to. |
1234 | */ |
1235 | if (aMediaDeviceName && *aMediaDeviceName) { |
1236 | for (auto& device : devices) { |
1237 | if (device->mRawName.EqualsASCII(aMediaDeviceName)) { |
1238 | aResult.AppendElement(device); |
1239 | LOG("%s: found aMediaDeviceName=%s", __func__, aMediaDeviceName); |
1240 | break; |
1241 | } |
1242 | } |
1243 | } else { |
1244 | aResult = std::move(devices); |
1245 | if (MOZ_LOG_TEST(gMediaManagerLog, mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gMediaManagerLog , mozilla::LogLevel::Debug)), 0))) { |
1246 | for (auto& device : aResult) { |
1247 | LOG("%s: appending device=%s", __func__, |
1248 | NS_ConvertUTF16toUTF8(device->mRawName).get()); |
1249 | } |
1250 | } |
1251 | } |
1252 | } |
1253 | |
1254 | RefPtr<LocalDeviceSetPromise> MediaManager::SelectSettings( |
1255 | const MediaStreamConstraints& aConstraints, CallerType aCallerType, |
1256 | RefPtr<LocalMediaDeviceSetRefCnt> aDevices) { |
1257 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1257); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1257; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1258 | |
1259 | // Algorithm accesses device capabilities code and must run on media thread. |
1260 | // Modifies passed-in aDevices. |
1261 | |
1262 | return MediaManager::Dispatch<LocalDeviceSetPromise>( |
1263 | __func__, [aConstraints, devices = std::move(aDevices), |
1264 | aCallerType](MozPromiseHolder<LocalDeviceSetPromise>& holder) { |
1265 | auto& devicesRef = *devices; |
1266 | |
1267 | // Since the advanced part of the constraints algorithm needs to know |
1268 | // when a candidate set is overconstrained (zero members), we must split |
1269 | // up the list into videos and audios, and put it back together again at |
1270 | // the end. |
1271 | |
1272 | nsTArray<RefPtr<LocalMediaDevice>> videos; |
1273 | nsTArray<RefPtr<LocalMediaDevice>> audios; |
1274 | |
1275 | for (const auto& device : devicesRef) { |
1276 | MOZ_ASSERT(device->Kind() == MediaDeviceKind::Videoinput ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(device->Kind() == MediaDeviceKind::Videoinput || device ->Kind() == MediaDeviceKind::Audioinput)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(device->Kind() == MediaDeviceKind ::Videoinput || device->Kind() == MediaDeviceKind::Audioinput ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput" ")"); do { *((volatile int*)__null) = 1277; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1277 | device->Kind() == MediaDeviceKind::Audioinput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(device->Kind() == MediaDeviceKind::Videoinput || device ->Kind() == MediaDeviceKind::Audioinput)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(device->Kind() == MediaDeviceKind ::Videoinput || device->Kind() == MediaDeviceKind::Audioinput ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "device->Kind() == MediaDeviceKind::Videoinput || device->Kind() == MediaDeviceKind::Audioinput" ")"); do { *((volatile int*)__null) = 1277; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1278 | if (device->Kind() == MediaDeviceKind::Videoinput) { |
1279 | videos.AppendElement(device); |
1280 | } else if (device->Kind() == MediaDeviceKind::Audioinput) { |
1281 | audios.AppendElement(device); |
1282 | } |
1283 | } |
1284 | devicesRef.Clear(); |
1285 | const char* badConstraint = nullptr; |
1286 | bool needVideo = IsOn(aConstraints.mVideo); |
1287 | bool needAudio = IsOn(aConstraints.mAudio); |
1288 | |
1289 | if (needVideo && videos.Length()) { |
1290 | badConstraint = MediaConstraintsHelper::SelectSettings( |
1291 | NormalizedConstraints(GetInvariant(aConstraints.mVideo)), videos, |
1292 | aCallerType); |
1293 | } |
1294 | if (!badConstraint && needAudio && audios.Length()) { |
1295 | badConstraint = MediaConstraintsHelper::SelectSettings( |
1296 | NormalizedConstraints(GetInvariant(aConstraints.mAudio)), audios, |
1297 | aCallerType); |
1298 | } |
1299 | if (badConstraint) { |
1300 | LOG("SelectSettings: bad constraint found! Calling error handler!"); |
1301 | nsString constraint; |
1302 | constraint.AssignASCII(badConstraint); |
1303 | holder.Reject( |
1304 | new MediaMgrError(MediaMgrError::Name::OverconstrainedError, "", |
1305 | constraint), |
1306 | __func__); |
1307 | return; |
1308 | } |
1309 | if (!needVideo == !videos.Length() && !needAudio == !audios.Length()) { |
1310 | for (auto& video : videos) { |
1311 | devicesRef.AppendElement(video); |
1312 | } |
1313 | for (auto& audio : audios) { |
1314 | devicesRef.AppendElement(audio); |
1315 | } |
1316 | } |
1317 | holder.Resolve(devices, __func__); |
1318 | }); |
1319 | } |
1320 | |
1321 | /** |
1322 | * Describes a requested task that handles response from the UI and sends |
1323 | * results back to the DOM. |
1324 | */ |
1325 | class GetUserMediaTask { |
1326 | public: |
1327 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GetUserMediaTask)public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<GetUserMediaTask>, "Reference-counted class " "GetUserMediaTask" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 1327; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("GetUserMediaTask"), (uint32_t)(sizeof(*this))); return (nsrefcnt)count; } MozExternalRefCountType Release(void ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 1327 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("GetUserMediaTask")); if (count == 0) { delete (this ); return 0; } return count; } using HasThreadSafeRefCnt = std ::true_type; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt ; public: |
1328 | GetUserMediaTask(uint64_t aWindowID, const ipc::PrincipalInfo& aPrincipalInfo, |
1329 | CallerType aCallerType) |
1330 | : mPrincipalInfo(aPrincipalInfo), |
1331 | mWindowID(aWindowID), |
1332 | mCallerType(aCallerType) {} |
1333 | |
1334 | virtual void Denied(MediaMgrError::Name aName, |
1335 | const nsCString& aMessage = ""_ns) = 0; |
1336 | |
1337 | virtual GetUserMediaStreamTask* AsGetUserMediaStreamTask() { return nullptr; } |
1338 | virtual SelectAudioOutputTask* AsSelectAudioOutputTask() { return nullptr; } |
1339 | |
1340 | uint64_t GetWindowID() const { return mWindowID; } |
1341 | enum CallerType CallerType() const { return mCallerType; } |
1342 | |
1343 | size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { |
1344 | size_t amount = aMallocSizeOf(this); |
1345 | // Assume mWindowListener is owned by MediaManager. |
1346 | // Assume mAudioDeviceListener and mVideoDeviceListener are owned by |
1347 | // mWindowListener. |
1348 | // Assume PrincipalInfo string buffers are shared. |
1349 | // Member types without support for accounting of pointees: |
1350 | // MozPromiseHolder, RefPtr<LocalMediaDevice>. |
1351 | // We don't have a good way to account for lambda captures for MozPromise |
1352 | // callbacks. |
1353 | return amount; |
1354 | } |
1355 | |
1356 | protected: |
1357 | virtual ~GetUserMediaTask() = default; |
1358 | |
1359 | // Call GetPrincipalKey again, if not private browing, this time with |
1360 | // persist = true, to promote deviceIds to persistent, in case they're not |
1361 | // already. Fire'n'forget. |
1362 | void PersistPrincipalKey() { |
1363 | if (IsPrincipalInfoPrivate(mPrincipalInfo)) { |
1364 | return; |
1365 | } |
1366 | media::GetPrincipalKey(mPrincipalInfo, true) |
1367 | ->Then( |
1368 | GetCurrentSerialEventTarget(), __func__, |
1369 | [](const media::PrincipalKeyPromise::ResolveOrRejectValue& aValue) { |
1370 | if (aValue.IsReject()) { |
1371 | LOG("Failed get Principal key. Persisting of deviceIds " |
1372 | "will be broken"); |
1373 | } |
1374 | }); |
1375 | } |
1376 | |
1377 | private: |
1378 | // Thread-safe (object) principal of Window with ID mWindowID |
1379 | const ipc::PrincipalInfo mPrincipalInfo; |
1380 | |
1381 | protected: |
1382 | // The ID of the not-necessarily-toplevel inner Window relevant global |
1383 | // object of the MediaDevices on which getUserMedia() was called |
1384 | const uint64_t mWindowID; |
1385 | // Whether the JS caller of getUserMedia() has system (subject) principal |
1386 | const enum CallerType mCallerType; |
1387 | }; |
1388 | |
1389 | /** |
1390 | * Describes a requested task that handles response from the UI to a |
1391 | * getUserMedia() request and sends results back to content. If the request |
1392 | * is allowed and device initialization succeeds, then the MozPromise is |
1393 | * resolved with a DOMMediaStream having a track or tracks for the approved |
1394 | * device or devices. |
1395 | */ |
1396 | class GetUserMediaStreamTask final : public GetUserMediaTask { |
1397 | public: |
1398 | GetUserMediaStreamTask( |
1399 | const MediaStreamConstraints& aConstraints, |
1400 | MozPromiseHolder<MediaManager::StreamPromise>&& aHolder, |
1401 | uint64_t aWindowID, RefPtr<GetUserMediaWindowListener> aWindowListener, |
1402 | RefPtr<DeviceListener> aAudioDeviceListener, |
1403 | RefPtr<DeviceListener> aVideoDeviceListener, |
1404 | const MediaEnginePrefs& aPrefs, const ipc::PrincipalInfo& aPrincipalInfo, |
1405 | enum CallerType aCallerType, bool aShouldFocusSource) |
1406 | : GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType), |
1407 | mConstraints(aConstraints), |
1408 | mHolder(std::move(aHolder)), |
1409 | mWindowListener(std::move(aWindowListener)), |
1410 | mAudioDeviceListener(std::move(aAudioDeviceListener)), |
1411 | mVideoDeviceListener(std::move(aVideoDeviceListener)), |
1412 | mPrefs(aPrefs), |
1413 | mShouldFocusSource(aShouldFocusSource), |
1414 | mManager(MediaManager::GetInstance()) {} |
1415 | |
1416 | void Allowed(RefPtr<LocalMediaDevice> aAudioDevice, |
1417 | RefPtr<LocalMediaDevice> aVideoDevice) { |
1418 | MOZ_ASSERT(aAudioDevice || aVideoDevice)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aAudioDevice || aVideoDevice)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aAudioDevice || aVideoDevice ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aAudioDevice || aVideoDevice", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioDevice || aVideoDevice" ")"); do { *((volatile int*)__null) = 1418; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1419 | mAudioDevice = std::move(aAudioDevice); |
1420 | mVideoDevice = std::move(aVideoDevice); |
1421 | // Reuse the same thread to save memory. |
1422 | MediaManager::Dispatch( |
1423 | NewRunnableMethod("GetUserMediaStreamTask::AllocateDevices", this, |
1424 | &GetUserMediaStreamTask::AllocateDevices)); |
1425 | } |
1426 | |
1427 | GetUserMediaStreamTask* AsGetUserMediaStreamTask() override { return this; } |
1428 | |
1429 | private: |
1430 | ~GetUserMediaStreamTask() override { |
1431 | if (!mHolder.IsEmpty()) { |
1432 | Fail(MediaMgrError::Name::NotAllowedError); |
1433 | } |
1434 | } |
1435 | |
1436 | void Fail(MediaMgrError::Name aName, const nsCString& aMessage = ""_ns, |
1437 | const nsString& aConstraint = u""_ns) { |
1438 | mHolder.Reject(MakeRefPtr<MediaMgrError>(aName, aMessage, aConstraint), |
1439 | __func__); |
1440 | // We add a disabled listener to the StreamListeners array until accepted |
1441 | // If this was the only active MediaStream, remove the window from the list. |
1442 | NS_DispatchToMainThread(NS_NewRunnableFunction( |
1443 | "DeviceListener::Stop", |
1444 | [audio = mAudioDeviceListener, video = mVideoDeviceListener] { |
1445 | if (audio) { |
1446 | audio->Stop(); |
1447 | } |
1448 | if (video) { |
1449 | video->Stop(); |
1450 | } |
1451 | })); |
1452 | } |
1453 | |
1454 | /** |
1455 | * Runs on a separate thread and is responsible for allocating devices. |
1456 | * |
1457 | * Do not run this on the main thread. |
1458 | */ |
1459 | void AllocateDevices() { |
1460 | MOZ_ASSERT(!NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1460; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1461 | LOG("GetUserMediaStreamTask::AllocateDevices()"); |
1462 | |
1463 | // Allocate a video or audio device and return a MediaStream via |
1464 | // PrepareDOMStream(). |
1465 | |
1466 | nsresult rv; |
1467 | const char* errorMsg = nullptr; |
1468 | const char* badConstraint = nullptr; |
1469 | |
1470 | if (mAudioDevice) { |
1471 | auto& constraints = GetInvariant(mConstraints.mAudio); |
1472 | rv = mAudioDevice->Allocate(constraints, mPrefs, mWindowID, |
1473 | &badConstraint); |
1474 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1475 | errorMsg = "Failed to allocate audiosource"; |
1476 | if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) { |
1477 | nsTArray<RefPtr<LocalMediaDevice>> devices; |
1478 | devices.AppendElement(mAudioDevice); |
1479 | badConstraint = MediaConstraintsHelper::SelectSettings( |
1480 | NormalizedConstraints(constraints), devices, mCallerType); |
1481 | } |
1482 | } |
1483 | } |
1484 | if (!errorMsg && mVideoDevice) { |
1485 | auto& constraints = GetInvariant(mConstraints.mVideo); |
1486 | rv = mVideoDevice->Allocate(constraints, mPrefs, mWindowID, |
1487 | &badConstraint); |
1488 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
1489 | errorMsg = "Failed to allocate videosource"; |
1490 | if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) { |
1491 | nsTArray<RefPtr<LocalMediaDevice>> devices; |
1492 | devices.AppendElement(mVideoDevice); |
1493 | badConstraint = MediaConstraintsHelper::SelectSettings( |
1494 | NormalizedConstraints(constraints), devices, mCallerType); |
1495 | } |
1496 | if (mAudioDevice) { |
1497 | mAudioDevice->Deallocate(); |
1498 | } |
1499 | } else { |
1500 | mVideoTrackingId.emplace(mVideoDevice->GetTrackingId()); |
1501 | } |
1502 | } |
1503 | if (errorMsg) { |
1504 | LOG("%s %" PRIu32"u", errorMsg, static_cast<uint32_t>(rv)); |
1505 | if (badConstraint) { |
1506 | Fail(MediaMgrError::Name::OverconstrainedError, ""_ns, |
1507 | NS_ConvertUTF8toUTF16(badConstraint)); |
1508 | } else { |
1509 | Fail(MediaMgrError::Name::NotReadableError, nsCString(errorMsg)); |
1510 | } |
1511 | NS_DispatchToMainThread( |
1512 | NS_NewRunnableFunction("MediaManager::SendPendingGUMRequest", []() { |
1513 | if (MediaManager* manager = MediaManager::GetIfExists()) { |
1514 | manager->SendPendingGUMRequest(); |
1515 | } |
1516 | })); |
1517 | return; |
1518 | } |
1519 | NS_DispatchToMainThread( |
1520 | NewRunnableMethod("GetUserMediaStreamTask::PrepareDOMStream", this, |
1521 | &GetUserMediaStreamTask::PrepareDOMStream)); |
1522 | } |
1523 | |
1524 | public: |
1525 | void Denied(MediaMgrError::Name aName, const nsCString& aMessage) override { |
1526 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1526; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1527 | Fail(aName, aMessage); |
1528 | } |
1529 | |
1530 | const MediaStreamConstraints& GetConstraints() { return mConstraints; } |
1531 | |
1532 | void PrimeVoiceProcessing() { |
1533 | mPrimingStream = MakeAndAddRef<PrimingCubebVoiceInputStream>(); |
1534 | mPrimingStream->Init(); |
1535 | } |
1536 | |
1537 | private: |
1538 | void PrepareDOMStream(); |
1539 | |
1540 | class PrimingCubebVoiceInputStream { |
1541 | class Listener final : public CubebInputStream::Listener { |
1542 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Listener, override)public: MozExternalRefCountType AddRef(void) override { static_assert (!std::is_destructible_v<Listener>, "Reference-counted class " "Listener" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1542); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 1542; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("Listener"), (uint32_t)(sizeof(*this))); return ( nsrefcnt)count; } MozExternalRefCountType Release(void) override { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1542); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 1542 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("Listener")); if (count == 0) { delete (this); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type ; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public:; |
1543 | |
1544 | private: |
1545 | ~Listener() = default; |
1546 | |
1547 | long DataCallback(const void*, long) override { |
1548 | MOZ_CRASH("Unexpected data callback")do { do { } while (false); MOZ_ReportCrash("" "Unexpected data callback" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1548); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected data callback" ")"); do { *((volatile int*)__null) = 1548; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1549 | } |
1550 | void StateCallback(cubeb_state) override {} |
1551 | void DeviceChangedCallback() override {} |
1552 | }; |
1553 | |
1554 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_EVENT_TARGET(public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<PrimingCubebVoiceInputStream>, "Reference-counted class " "PrimingCubebVoiceInputStream" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("PrimingCubebVoiceInputStream"), (uint32_t)(sizeof (*this))); return (nsrefcnt)count; } MozExternalRefCountType Release (void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 1555 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("PrimingCubebVoiceInputStream")); if (count == 0) { :: mozilla::detail::ProxyDeleteVoid( "ProxyDelete " "PrimingCubebVoiceInputStream" , mCubebThread.GetEventTarget(), this, [](void* self) { delete static_cast<PrimingCubebVoiceInputStream*>(self); }); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type ; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
1555 | PrimingCubebVoiceInputStream, mCubebThread.GetEventTarget())public: MozExternalRefCountType AddRef(void) { static_assert( !std::is_destructible_v<PrimingCubebVoiceInputStream>, "Reference-counted class " "PrimingCubebVoiceInputStream" " should not have a public destructor. " "Make this class's destructor non-public"); do { static_assert ( mozilla::detail::AssertionConditionType<decltype(int32_t (mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this ), (count), ("PrimingCubebVoiceInputStream"), (uint32_t)(sizeof (*this))); return (nsrefcnt)count; } MozExternalRefCountType Release (void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 1555 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), ( count), ("PrimingCubebVoiceInputStream")); if (count == 0) { :: mozilla::detail::ProxyDeleteVoid( "ProxyDelete " "PrimingCubebVoiceInputStream" , mCubebThread.GetEventTarget(), this, [](void* self) { delete static_cast<PrimingCubebVoiceInputStream*>(self); }); return 0; } return count; } using HasThreadSafeRefCnt = std::true_type ; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public: |
1556 | |
1557 | public: |
1558 | void Init() { |
1559 | mCubebThread.GetEventTarget()->Dispatch( |
1560 | NS_NewRunnableFunction(__func__, [this, self = RefPtr(this)] { |
1561 | mCubebThread.AssertOnCurrentThread(); |
1562 | LOG("Priming voice processing with stream %p", this); |
1563 | TRACE("PrimingCubebVoiceInputStream::Init")AutoTracer trace(gAudioCallbackTraceLogger, "PrimingCubebVoiceInputStream::Init" );; |
1564 | const cubeb_devid default_device = nullptr; |
1565 | const uint32_t mono = 1; |
1566 | const uint32_t rate = CubebUtils::PreferredSampleRate(false); |
1567 | const bool isVoice = true; |
1568 | mCubebStream = |
1569 | CubebInputStream::Create(default_device, mono, rate, isVoice, |
1570 | MakeRefPtr<Listener>().get()); |
1571 | })); |
1572 | } |
1573 | |
1574 | private: |
1575 | ~PrimingCubebVoiceInputStream() { |
1576 | mCubebThread.AssertOnCurrentThread(); |
1577 | LOG("Releasing primed voice processing stream %p", this); |
1578 | mCubebStream = nullptr; |
1579 | } |
1580 | |
1581 | const EventTargetCapability<nsISerialEventTarget> mCubebThread = |
1582 | EventTargetCapability<nsISerialEventTarget>( |
1583 | TaskQueue::Create(CubebUtils::GetCubebOperationThread(), |
1584 | "PrimingCubebInputStream::mCubebThread") |
1585 | .get()); |
1586 | UniquePtr<CubebInputStream> mCubebStream MOZ_GUARDED_BY(mCubebThread)__attribute__((guarded_by(mCubebThread))); |
1587 | }; |
1588 | |
1589 | // Constraints derived from those passed to getUserMedia() but adjusted for |
1590 | // preferences, defaults, and security |
1591 | const MediaStreamConstraints mConstraints; |
1592 | |
1593 | MozPromiseHolder<MediaManager::StreamPromise> mHolder; |
1594 | // GetUserMediaWindowListener with which DeviceListeners are registered |
1595 | const RefPtr<GetUserMediaWindowListener> mWindowListener; |
1596 | const RefPtr<DeviceListener> mAudioDeviceListener; |
1597 | const RefPtr<DeviceListener> mVideoDeviceListener; |
1598 | // MediaDevices are set when selected and Allowed() by the UI. |
1599 | RefPtr<LocalMediaDevice> mAudioDevice; |
1600 | RefPtr<LocalMediaDevice> mVideoDevice; |
1601 | RefPtr<PrimingCubebVoiceInputStream> mPrimingStream; |
1602 | // Tracking id unique for a video frame source. Set when the corresponding |
1603 | // device has been allocated. |
1604 | Maybe<TrackingId> mVideoTrackingId; |
1605 | // Copy of MediaManager::mPrefs |
1606 | const MediaEnginePrefs mPrefs; |
1607 | // media.getusermedia.window.focus_source.enabled |
1608 | const bool mShouldFocusSource; |
1609 | // The MediaManager is referenced at construction so that it won't be |
1610 | // created after its ShutdownBlocker would run. |
1611 | const RefPtr<MediaManager> mManager; |
1612 | }; |
1613 | |
1614 | /** |
1615 | * Creates a MediaTrack, attaches a listener and resolves a MozPromise to |
1616 | * provide the stream to the DOM. |
1617 | * |
1618 | * All of this must be done on the main thread! |
1619 | */ |
1620 | void GetUserMediaStreamTask::PrepareDOMStream() { |
1621 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1621; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1622 | LOG("GetUserMediaStreamTask::PrepareDOMStream()"); |
1623 | nsGlobalWindowInner* window = |
1624 | nsGlobalWindowInner::GetInnerWindowWithId(mWindowID); |
1625 | |
1626 | // We're on main-thread, and the windowlist can only |
1627 | // be invalidated from the main-thread (see OnNavigation) |
1628 | if (!mManager->IsWindowListenerStillActive(mWindowListener)) { |
1629 | // This window is no longer live. mListener has already been removed. |
1630 | return; |
1631 | } |
1632 | |
1633 | MediaTrackGraph::GraphDriverType graphDriverType = |
1634 | mAudioDevice ? MediaTrackGraph::AUDIO_THREAD_DRIVER |
1635 | : MediaTrackGraph::SYSTEM_THREAD_DRIVER; |
1636 | MediaTrackGraph* mtg = MediaTrackGraph::GetInstance( |
1637 | graphDriverType, window, MediaTrackGraph::REQUEST_DEFAULT_SAMPLE_RATE, |
1638 | MediaTrackGraph::DEFAULT_OUTPUT_DEVICE); |
1639 | |
1640 | auto domStream = MakeRefPtr<DOMMediaStream>(window); |
1641 | RefPtr<LocalTrackSource> audioTrackSource; |
1642 | RefPtr<LocalTrackSource> videoTrackSource; |
1643 | nsCOMPtr<nsIPrincipal> principal; |
1644 | RefPtr<PeerIdentity> peerIdentity = nullptr; |
1645 | if (!mConstraints.mPeerIdentity.IsEmpty()) { |
1646 | peerIdentity = new PeerIdentity(mConstraints.mPeerIdentity); |
1647 | principal = NullPrincipal::CreateWithInheritedAttributes( |
1648 | window->GetExtantDoc()->NodePrincipal()); |
1649 | } else { |
1650 | principal = window->GetExtantDoc()->NodePrincipal(); |
1651 | } |
1652 | RefPtr<GenericNonExclusivePromise> firstFramePromise; |
1653 | if (mAudioDevice) { |
1654 | if (mAudioDevice->GetMediaSource() == MediaSourceEnum::AudioCapture) { |
1655 | // AudioCapture is a special case, here, in the sense that we're not |
1656 | // really using the audio source and the SourceMediaTrack, which acts |
1657 | // as placeholders. We re-route a number of tracks internally in the |
1658 | // MTG and mix them down instead. |
1659 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle " "MediaSourceEnum::AudioCapture. This must be fixed with UX " "before shipping.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1662) |
1660 | "MediaCaptureWindowState doesn't handle "NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle " "MediaSourceEnum::AudioCapture. This must be fixed with UX " "before shipping.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1662) |
1661 | "MediaSourceEnum::AudioCapture. This must be fixed with UX "NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle " "MediaSourceEnum::AudioCapture. This must be fixed with UX " "before shipping.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1662) |
1662 | "before shipping.")NS_DebugBreak(NS_DEBUG_WARNING, "MediaCaptureWindowState doesn't handle " "MediaSourceEnum::AudioCapture. This must be fixed with UX " "before shipping.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1662); |
1663 | auto audioCaptureSource = MakeRefPtr<AudioCaptureTrackSource>( |
1664 | principal, window, u"Window audio capture"_ns, |
1665 | mtg->CreateAudioCaptureTrack(), peerIdentity); |
1666 | audioTrackSource = audioCaptureSource; |
1667 | RefPtr<MediaStreamTrack> track = new dom::AudioStreamTrack( |
1668 | window, audioCaptureSource->InputTrack(), audioCaptureSource); |
1669 | domStream->AddTrackInternal(track); |
1670 | } else { |
1671 | const nsString& audioDeviceName = mAudioDevice->mName; |
1672 | RefPtr<MediaTrack> track; |
1673 | #ifdef MOZ_WEBRTC1 |
1674 | if (mAudioDevice->IsFake()) { |
1675 | track = mtg->CreateSourceTrack(MediaSegment::AUDIO); |
1676 | } else { |
1677 | track = AudioProcessingTrack::Create(mtg); |
1678 | track->Suspend(); // Microphone source resumes in SetTrack |
1679 | } |
1680 | #else |
1681 | track = mtg->CreateSourceTrack(MediaSegment::AUDIO); |
1682 | #endif |
1683 | audioTrackSource = new LocalTrackSource( |
1684 | principal, audioDeviceName, mAudioDeviceListener, |
1685 | mAudioDevice->GetMediaSource(), track, peerIdentity); |
1686 | MOZ_ASSERT(MediaManager::IsOn(mConstraints.mAudio))do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsOn(mConstraints.mAudio))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(MediaManager::IsOn(mConstraints.mAudio)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaManager::IsOn(mConstraints.mAudio)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsOn(mConstraints.mAudio)" ")"); do { *((volatile int*)__null) = 1686; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1687 | RefPtr<MediaStreamTrack> domTrack = new dom::AudioStreamTrack( |
1688 | window, track, audioTrackSource, dom::MediaStreamTrackState::Live, |
1689 | false, GetInvariant(mConstraints.mAudio)); |
1690 | domStream->AddTrackInternal(domTrack); |
1691 | } |
1692 | } |
1693 | if (mVideoDevice) { |
1694 | const nsString& videoDeviceName = mVideoDevice->mName; |
1695 | RefPtr<MediaTrack> track = mtg->CreateSourceTrack(MediaSegment::VIDEO); |
1696 | videoTrackSource = new LocalTrackSource( |
1697 | principal, videoDeviceName, mVideoDeviceListener, |
1698 | mVideoDevice->GetMediaSource(), track, peerIdentity, *mVideoTrackingId); |
1699 | MOZ_ASSERT(MediaManager::IsOn(mConstraints.mVideo))do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsOn(mConstraints.mVideo))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(MediaManager::IsOn(mConstraints.mVideo)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaManager::IsOn(mConstraints.mVideo)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsOn(mConstraints.mVideo)" ")"); do { *((volatile int*)__null) = 1699; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1700 | RefPtr<MediaStreamTrack> domTrack = new dom::VideoStreamTrack( |
1701 | window, track, videoTrackSource, dom::MediaStreamTrackState::Live, |
1702 | false, GetInvariant(mConstraints.mVideo)); |
1703 | domStream->AddTrackInternal(domTrack); |
1704 | switch (mVideoDevice->GetMediaSource()) { |
1705 | case MediaSourceEnum::Browser: |
1706 | case MediaSourceEnum::Screen: |
1707 | case MediaSourceEnum::Window: |
1708 | // Wait for first frame for screen-sharing devices, to ensure |
1709 | // with and height settings are available immediately, to pass wpt. |
1710 | firstFramePromise = mVideoDevice->Source()->GetFirstFramePromise(); |
1711 | break; |
1712 | default: |
1713 | break; |
1714 | } |
1715 | } |
1716 | |
1717 | if (!domStream || (!audioTrackSource && !videoTrackSource) || |
1718 | sHasMainThreadShutdown) { |
1719 | LOG("Returning error for getUserMedia() - no stream"); |
1720 | |
1721 | mHolder.Reject( |
1722 | MakeRefPtr<MediaMgrError>( |
1723 | MediaMgrError::Name::AbortError, |
1724 | sHasMainThreadShutdown ? "In shutdown"_ns : "No stream."_ns), |
1725 | __func__); |
1726 | return; |
1727 | } |
1728 | |
1729 | // Activate our device listeners. We'll call Start() on the source when we |
1730 | // get a callback that the MediaStream has started consuming. The listener |
1731 | // is freed when the page is invalidated (on navigation or close). |
1732 | if (mAudioDeviceListener) { |
1733 | mWindowListener->Activate(mAudioDeviceListener, mAudioDevice, |
1734 | std::move(audioTrackSource)); |
1735 | } |
1736 | if (mVideoDeviceListener) { |
1737 | mWindowListener->Activate(mVideoDeviceListener, mVideoDevice, |
1738 | std::move(videoTrackSource)); |
1739 | } |
1740 | |
1741 | // Dispatch to the media thread to ask it to start the sources, because that |
1742 | // can take a while. |
1743 | typedef DeviceListener::DeviceListenerPromise PromiseType; |
1744 | AutoTArray<RefPtr<PromiseType>, 2> promises; |
1745 | if (mAudioDeviceListener) { |
1746 | promises.AppendElement(mAudioDeviceListener->InitializeAsync()); |
1747 | } |
1748 | if (mVideoDeviceListener) { |
1749 | promises.AppendElement(mVideoDeviceListener->InitializeAsync()); |
1750 | } |
1751 | PromiseType::All(GetMainThreadSerialEventTarget(), promises) |
1752 | ->Then( |
1753 | GetMainThreadSerialEventTarget(), __func__, |
1754 | [manager = mManager, windowListener = mWindowListener, |
1755 | firstFramePromise] { |
1756 | LOG("GetUserMediaStreamTask::PrepareDOMStream: starting success " |
1757 | "callback following InitializeAsync()"); |
1758 | // Initiating and starting devices succeeded. |
1759 | windowListener->ChromeAffectingStateChanged(); |
1760 | manager->SendPendingGUMRequest(); |
1761 | if (!firstFramePromise) { |
1762 | return DeviceListener::DeviceListenerPromise::CreateAndResolve( |
1763 | true, __func__); |
1764 | } |
1765 | RefPtr<DeviceListener::DeviceListenerPromise> resolvePromise = |
1766 | firstFramePromise->Then( |
1767 | GetMainThreadSerialEventTarget(), __func__, |
1768 | [] { |
1769 | return DeviceListener::DeviceListenerPromise:: |
1770 | CreateAndResolve(true, __func__); |
1771 | }, |
1772 | [] { |
1773 | return DeviceListener::DeviceListenerPromise:: |
1774 | CreateAndReject(MakeRefPtr<MediaMgrError>( |
1775 | MediaMgrError::Name::AbortError, |
1776 | "In shutdown"), |
1777 | __func__); |
1778 | }); |
1779 | return resolvePromise; |
1780 | }, |
1781 | [audio = mAudioDeviceListener, |
1782 | video = mVideoDeviceListener](RefPtr<MediaMgrError>&& aError) { |
1783 | LOG("GetUserMediaStreamTask::PrepareDOMStream: starting failure " |
1784 | "callback following InitializeAsync()"); |
1785 | if (audio) { |
1786 | audio->Stop(); |
1787 | } |
1788 | if (video) { |
1789 | video->Stop(); |
1790 | } |
1791 | return DeviceListener::DeviceListenerPromise::CreateAndReject( |
1792 | aError, __func__); |
1793 | }) |
1794 | ->Then( |
1795 | GetMainThreadSerialEventTarget(), __func__, |
1796 | [holder = std::move(mHolder), domStream, callerType = mCallerType, |
1797 | shouldFocus = mShouldFocusSource, videoDevice = mVideoDevice]( |
1798 | const DeviceListener::DeviceListenerPromise::ResolveOrRejectValue& |
1799 | aValue) mutable { |
1800 | if (aValue.IsResolve()) { |
1801 | if (auto* mgr = MediaManager::GetIfExists(); |
1802 | mgr && !sHasMainThreadShutdown && videoDevice && |
1803 | callerType == CallerType::NonSystem && shouldFocus) { |
1804 | // Device was successfully started. Attempt to focus the |
1805 | // source. |
1806 | MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1814); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1807 | mgr->mMediaThread->Dispatch(NS_NewRunnableFunction(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1814); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1808 | "GetUserMediaStreamTask::FocusOnSelectedSource",do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1814); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1809 | [videoDevice = std::move(videoDevice)] {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1814); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1810 | nsresult rv = videoDevice->FocusOnSelectedSource();do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1814); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1811 | if (NS_FAILED(rv)) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1814); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1812 | LOG("FocusOnSelectedSource failed");do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1814); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1813 | }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1814); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1814 | })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( "GetUserMediaStreamTask::FocusOnSelectedSource" , [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice ->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!! (NS_FAILED_impl(rv)), 0)))) { LOG("FocusOnSelectedSource failed" ); } })))), 1)))), 1))) { } else { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(false)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1814); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mgr->mMediaThread->Dispatch(NS_NewRunnableFunction( \"GetUserMediaStreamTask::FocusOnSelectedSource\", [videoDevice = std::move(videoDevice)] { nsresult rv = videoDevice->FocusOnSelectedSource(); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { LOG(\"FocusOnSelectedSource failed\"); } })))" ")"); do { *((volatile int*)__null) = 1814; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1815 | } |
1816 | |
1817 | holder.Resolve(domStream, __func__); |
1818 | } else { |
1819 | holder.Reject(aValue.RejectValue(), __func__); |
1820 | } |
1821 | }); |
1822 | |
1823 | PersistPrincipalKey(); |
1824 | } |
1825 | |
1826 | /** |
1827 | * Describes a requested task that handles response from the UI to a |
1828 | * selectAudioOutput() request and sends results back to content. If the |
1829 | * request is allowed, then the MozPromise is resolved with a MediaDevice |
1830 | * for the approved device. |
1831 | */ |
1832 | class SelectAudioOutputTask final : public GetUserMediaTask { |
1833 | public: |
1834 | SelectAudioOutputTask(MozPromiseHolder<LocalDevicePromise>&& aHolder, |
1835 | uint64_t aWindowID, enum CallerType aCallerType, |
1836 | const ipc::PrincipalInfo& aPrincipalInfo) |
1837 | : GetUserMediaTask(aWindowID, aPrincipalInfo, aCallerType), |
1838 | mHolder(std::move(aHolder)) {} |
1839 | |
1840 | void Allowed(RefPtr<LocalMediaDevice> aAudioOutput) { |
1841 | MOZ_ASSERT(aAudioOutput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aAudioOutput)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aAudioOutput))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aAudioOutput", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioOutput" ")"); do { *((volatile int*)__null) = 1841; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1842 | mHolder.Resolve(std::move(aAudioOutput), __func__); |
1843 | PersistPrincipalKey(); |
1844 | } |
1845 | |
1846 | void Denied(MediaMgrError::Name aName, const nsCString& aMessage) override { |
1847 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1847; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1848 | Fail(aName, aMessage); |
1849 | } |
1850 | |
1851 | SelectAudioOutputTask* AsSelectAudioOutputTask() override { return this; } |
1852 | |
1853 | private: |
1854 | ~SelectAudioOutputTask() override { |
1855 | if (!mHolder.IsEmpty()) { |
1856 | Fail(MediaMgrError::Name::NotAllowedError); |
1857 | } |
1858 | } |
1859 | |
1860 | void Fail(MediaMgrError::Name aName, const nsCString& aMessage = ""_ns) { |
1861 | mHolder.Reject(MakeRefPtr<MediaMgrError>(aName, aMessage), __func__); |
1862 | } |
1863 | |
1864 | private: |
1865 | MozPromiseHolder<LocalDevicePromise> mHolder; |
1866 | }; |
1867 | |
1868 | /* static */ |
1869 | void MediaManager::GuessVideoDeviceGroupIDs(MediaDeviceSet& aDevices, |
1870 | const MediaDeviceSet& aAudios) { |
1871 | // Run the logic in a lambda to avoid duplication. |
1872 | auto updateGroupIdIfNeeded = [&](RefPtr<MediaDevice>& aVideo, |
1873 | const MediaDeviceKind aKind) -> bool { |
1874 | MOZ_ASSERT(aVideo->mKind == MediaDeviceKind::Videoinput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aVideo->mKind == MediaDeviceKind::Videoinput)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aVideo->mKind == MediaDeviceKind::Videoinput))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("aVideo->mKind == MediaDeviceKind::Videoinput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVideo->mKind == MediaDeviceKind::Videoinput" ")"); do { *((volatile int*)__null) = 1874; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1875 | MOZ_ASSERT(aKind == MediaDeviceKind::Audioinput ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind ::Audiooutput)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput" ")"); do { *((volatile int*)__null) = 1876; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1876 | aKind == MediaDeviceKind::Audiooutput)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind ::Audiooutput)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKind == MediaDeviceKind::Audioinput || aKind == MediaDeviceKind::Audiooutput" ")"); do { *((volatile int*)__null) = 1876; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1877 | // This will store the new group id if a match is found. |
1878 | nsString newVideoGroupID; |
1879 | // If the group id needs to be updated this will become true. It is |
1880 | // necessary when the new group id is an empty string. Without this extra |
1881 | // variable to signal the update, we would resort to test if |
1882 | // `newVideoGroupId` is empty. However, |
1883 | // that check does not work when the new group id is an empty string. |
1884 | bool updateGroupId = false; |
1885 | for (const RefPtr<MediaDevice>& dev : aAudios) { |
1886 | if (dev->mKind != aKind) { |
1887 | continue; |
1888 | } |
1889 | if (!FindInReadable(aVideo->mRawName, dev->mRawName)) { |
1890 | continue; |
1891 | } |
1892 | if (newVideoGroupID.IsEmpty()) { |
1893 | // This is only expected on first match. If that's the only match group |
1894 | // id will be updated to this one at the end of the loop. |
1895 | updateGroupId = true; |
1896 | newVideoGroupID = dev->mRawGroupID; |
1897 | } else { |
1898 | // More than one device found, it is impossible to know which group id |
1899 | // is the correct one. |
1900 | updateGroupId = false; |
1901 | newVideoGroupID = u""_ns; |
1902 | break; |
1903 | } |
1904 | } |
1905 | if (updateGroupId) { |
1906 | aVideo = MediaDevice::CopyWithNewRawGroupId(aVideo, newVideoGroupID); |
1907 | return true; |
1908 | } |
1909 | return false; |
1910 | }; |
1911 | |
1912 | for (RefPtr<MediaDevice>& video : aDevices) { |
1913 | if (video->mKind != MediaDeviceKind::Videoinput) { |
1914 | continue; |
1915 | } |
1916 | if (updateGroupIdIfNeeded(video, MediaDeviceKind::Audioinput)) { |
1917 | // GroupId has been updated, continue to the next video device |
1918 | continue; |
1919 | } |
1920 | // GroupId has not been updated, check among the outputs |
1921 | updateGroupIdIfNeeded(video, MediaDeviceKind::Audiooutput); |
1922 | } |
1923 | } |
1924 | |
1925 | namespace { |
1926 | |
1927 | // Class to hold the promise used to request device access and to resolve |
1928 | // even if |task| does not run, either because GeckoViewPermissionProcessChild |
1929 | // gets destroyed before ask-device-permission receives its |
1930 | // got-device-permission reply, or because the media thread is no longer |
1931 | // available. In either case, the process is shutting down so the result is |
1932 | // not important. Reject with a dummy error so the following Then-handler can |
1933 | // resolve with an empty set, so that callers do not need to handle rejection. |
1934 | class DeviceAccessRequestPromiseHolderWithFallback |
1935 | : public MozPromiseHolder<MozPromise< |
1936 | CamerasAccessStatus, mozilla::ipc::ResponseRejectReason, true>> { |
1937 | public: |
1938 | DeviceAccessRequestPromiseHolderWithFallback() = default; |
1939 | DeviceAccessRequestPromiseHolderWithFallback( |
1940 | DeviceAccessRequestPromiseHolderWithFallback&&) = default; |
1941 | ~DeviceAccessRequestPromiseHolderWithFallback() { |
1942 | if (!IsEmpty()) { |
1943 | Reject(ipc::ResponseRejectReason::ChannelClosed, __func__); |
1944 | } |
1945 | } |
1946 | }; |
1947 | |
1948 | } // anonymous namespace |
1949 | |
1950 | MediaManager::DeviceEnumerationParams::DeviceEnumerationParams( |
1951 | dom::MediaSourceEnum aInputType, DeviceType aType, |
1952 | nsAutoCString aForcedDeviceName) |
1953 | : mInputType(aInputType), |
1954 | mType(aType), |
1955 | mForcedDeviceName(std::move(aForcedDeviceName)) { |
1956 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1956; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1957 | MOZ_ASSERT(mInputType != dom::MediaSourceEnum::Other)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mInputType != dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(mInputType != dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mInputType != dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInputType != dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 1957; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1958 | MOZ_ASSERT_IF(!mForcedDeviceName.IsEmpty(), mType == DeviceType::Real)do { if (!mForcedDeviceName.IsEmpty()) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(mType == DeviceType ::Real)>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mType == DeviceType::Real))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mType == DeviceType::Real", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mType == DeviceType::Real" ")"); do { *((volatile int*)__null) = 1958; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1959 | } |
1960 | |
1961 | MediaManager::VideoDeviceEnumerationParams::VideoDeviceEnumerationParams( |
1962 | dom::MediaSourceEnum aInputType, DeviceType aType, |
1963 | nsAutoCString aForcedDeviceName, nsAutoCString aForcedMicrophoneName) |
1964 | : DeviceEnumerationParams(aInputType, aType, std::move(aForcedDeviceName)), |
1965 | mForcedMicrophoneName(std::move(aForcedMicrophoneName)) { |
1966 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1966); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1966; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1967 | MOZ_ASSERT_IF(!mForcedMicrophoneName.IsEmpty(),do { if (!mForcedMicrophoneName.IsEmpty()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(mInputType == dom::MediaSourceEnum::Camera)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInputType == dom::MediaSourceEnum ::Camera))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 1968; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1968 | mInputType == dom::MediaSourceEnum::Camera)do { if (!mForcedMicrophoneName.IsEmpty()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(mInputType == dom::MediaSourceEnum::Camera)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mInputType == dom::MediaSourceEnum ::Camera))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 1968; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1969 | MOZ_ASSERT_IF(!mForcedMicrophoneName.IsEmpty(), mType == DeviceType::Real)do { if (!mForcedMicrophoneName.IsEmpty()) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(mType == DeviceType::Real)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mType == DeviceType::Real))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("mType == DeviceType::Real" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mType == DeviceType::Real" ")"); do { *((volatile int*)__null) = 1969; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1970 | } |
1971 | |
1972 | MediaManager::EnumerationParams::EnumerationParams( |
1973 | EnumerationFlags aFlags, Maybe<VideoDeviceEnumerationParams> aVideo, |
1974 | Maybe<DeviceEnumerationParams> aAudio) |
1975 | : mFlags(aFlags), mVideo(std::move(aVideo)), mAudio(std::move(aAudio)) { |
1976 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 1976; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1977 | MOZ_ASSERT_IF(mVideo, MediaEngineSource::IsVideo(mVideo->mInputType))do { if (mVideo) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(MediaEngineSource::IsVideo(mVideo->mInputType ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(MediaEngineSource::IsVideo(mVideo->mInputType)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaEngineSource::IsVideo(mVideo->mInputType)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaEngineSource::IsVideo(mVideo->mInputType)" ")"); do { *((volatile int*)__null) = 1977; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1978 | MOZ_ASSERT_IF(mVideo && !mVideo->mForcedDeviceName.IsEmpty(),do { if (mVideo && !mVideo->mForcedDeviceName.IsEmpty ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mVideo->mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1979); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 1979; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1979 | mVideo->mInputType == dom::MediaSourceEnum::Camera)do { if (mVideo && !mVideo->mForcedDeviceName.IsEmpty ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mVideo->mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1979); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 1979; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1980 | MOZ_ASSERT_IF(mVideo && mVideo->mType == DeviceType::Fake,do { if (mVideo && mVideo->mType == DeviceType::Fake ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mVideo->mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 1981; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1981 | mVideo->mInputType == dom::MediaSourceEnum::Camera)do { if (mVideo && mVideo->mType == DeviceType::Fake ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mVideo->mInputType == dom::MediaSourceEnum::Camera )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mVideo->mInputType == dom::MediaSourceEnum::Camera ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mVideo->mInputType == dom::MediaSourceEnum::Camera", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mVideo->mInputType == dom::MediaSourceEnum::Camera" ")"); do { *((volatile int*)__null) = 1981; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1982 | MOZ_ASSERT_IF(mAudio, MediaEngineSource::IsAudio(mAudio->mInputType))do { if (mAudio) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(MediaEngineSource::IsAudio(mAudio->mInputType ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(MediaEngineSource::IsAudio(mAudio->mInputType)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaEngineSource::IsAudio(mAudio->mInputType)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaEngineSource::IsAudio(mAudio->mInputType)" ")"); do { *((volatile int*)__null) = 1982; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1983 | MOZ_ASSERT_IF(mAudio && !mAudio->mForcedDeviceName.IsEmpty(),do { if (mAudio && !mAudio->mForcedDeviceName.IsEmpty ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1984); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone" ")"); do { *((volatile int*)__null) = 1984; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1984 | mAudio->mInputType == dom::MediaSourceEnum::Microphone)do { if (mAudio && !mAudio->mForcedDeviceName.IsEmpty ()) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1984); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone" ")"); do { *((volatile int*)__null) = 1984; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1985 | MOZ_ASSERT_IF(mAudio && mAudio->mType == DeviceType::Fake,do { if (mAudio && mAudio->mType == DeviceType::Fake ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone" ")"); do { *((volatile int*)__null) = 1986; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
1986 | mAudio->mInputType == dom::MediaSourceEnum::Microphone)do { if (mAudio && mAudio->mType == DeviceType::Fake ) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(mAudio->mInputType == dom::MediaSourceEnum::Microphone )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mAudio->mInputType == dom::MediaSourceEnum::Microphone ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mAudio->mInputType == dom::MediaSourceEnum::Microphone", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 1986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAudio->mInputType == dom::MediaSourceEnum::Microphone" ")"); do { *((volatile int*)__null) = 1986; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1987 | } |
1988 | |
1989 | bool MediaManager::EnumerationParams::HasFakeCams() const { |
1990 | return mVideo |
1991 | .map([](const auto& aDev) { return aDev.mType == DeviceType::Fake; }) |
1992 | .valueOr(false); |
1993 | } |
1994 | |
1995 | bool MediaManager::EnumerationParams::HasFakeMics() const { |
1996 | return mAudio |
1997 | .map([](const auto& aDev) { return aDev.mType == DeviceType::Fake; }) |
1998 | .valueOr(false); |
1999 | } |
2000 | |
2001 | bool MediaManager::EnumerationParams::RealDeviceRequested() const { |
2002 | auto isReal = [](const auto& aDev) { return aDev.mType == DeviceType::Real; }; |
2003 | return mVideo.map(isReal).valueOr(false) || |
2004 | mAudio.map(isReal).valueOr(false) || |
2005 | mFlags.contains(EnumerationFlag::EnumerateAudioOutputs); |
2006 | } |
2007 | |
2008 | MediaSourceEnum MediaManager::EnumerationParams::VideoInputType() const { |
2009 | return mVideo.map([](const auto& aDev) { return aDev.mInputType; }) |
2010 | .valueOr(MediaSourceEnum::Other); |
2011 | } |
2012 | |
2013 | MediaSourceEnum MediaManager::EnumerationParams::AudioInputType() const { |
2014 | return mAudio.map([](const auto& aDev) { return aDev.mInputType; }) |
2015 | .valueOr(MediaSourceEnum::Other); |
2016 | } |
2017 | |
2018 | /* static */ MediaManager::EnumerationParams |
2019 | MediaManager::CreateEnumerationParams(dom::MediaSourceEnum aVideoInputType, |
2020 | dom::MediaSourceEnum aAudioInputType, |
2021 | EnumerationFlags aFlags) { |
2022 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2022; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2023 | MOZ_ASSERT_IF(!MediaEngineSource::IsVideo(aVideoInputType),do { if (!MediaEngineSource::IsVideo(aVideoInputType)) { do { static_assert( mozilla::detail::AssertionConditionType<decltype (aVideoInputType == dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aVideoInputType == dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aVideoInputType == dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVideoInputType == dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 2024; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2024 | aVideoInputType == dom::MediaSourceEnum::Other)do { if (!MediaEngineSource::IsVideo(aVideoInputType)) { do { static_assert( mozilla::detail::AssertionConditionType<decltype (aVideoInputType == dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aVideoInputType == dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aVideoInputType == dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2024); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVideoInputType == dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 2024; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2025 | MOZ_ASSERT_IF(!MediaEngineSource::IsAudio(aAudioInputType),do { if (!MediaEngineSource::IsAudio(aAudioInputType)) { do { static_assert( mozilla::detail::AssertionConditionType<decltype (aAudioInputType == dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aAudioInputType == dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aAudioInputType == dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioInputType == dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 2026; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2026 | aAudioInputType == dom::MediaSourceEnum::Other)do { if (!MediaEngineSource::IsAudio(aAudioInputType)) { do { static_assert( mozilla::detail::AssertionConditionType<decltype (aAudioInputType == dom::MediaSourceEnum::Other)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aAudioInputType == dom::MediaSourceEnum::Other))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aAudioInputType == dom::MediaSourceEnum::Other" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAudioInputType == dom::MediaSourceEnum::Other" ")"); do { *((volatile int*)__null) = 2026; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2027 | const bool forceFakes = aFlags.contains(EnumerationFlag::ForceFakes); |
2028 | const bool fakeByPref = Preferences::GetBool("media.navigator.streams.fake"); |
2029 | Maybe<VideoDeviceEnumerationParams> videoParams; |
2030 | Maybe<DeviceEnumerationParams> audioParams; |
2031 | nsAutoCString audioDev; |
2032 | bool audioDevRead = false; |
2033 | constexpr const char* VIDEO_DEV_NAME = "media.video_loopback_dev"; |
2034 | constexpr const char* AUDIO_DEV_NAME = "media.audio_loopback_dev"; |
2035 | const auto ensureDev = [](const char* aPref, nsAutoCString* aLoopDev, |
2036 | bool* aPrefRead) { |
2037 | if (aPrefRead) { |
2038 | if (*aPrefRead) { |
2039 | return; |
2040 | } |
2041 | *aPrefRead = true; |
2042 | } |
2043 | |
2044 | if (NS_FAILED(Preferences::GetCString(aPref, *aLoopDev))((bool)(__builtin_expect(!!(NS_FAILED_impl(Preferences::GetCString (aPref, *aLoopDev))), 0)))) { |
2045 | // Ensure we fall back to an empty string if reading the pref failed. |
2046 | aLoopDev->SetIsVoid(true); |
2047 | } |
2048 | }; |
2049 | if (MediaEngineSource::IsVideo(aVideoInputType)) { |
2050 | nsAutoCString videoDev; |
2051 | DeviceType type = DeviceType::Real; |
2052 | if (aVideoInputType == MediaSourceEnum::Camera) { |
2053 | // Fake and loopback devices are supported for only Camera. |
2054 | if (forceFakes) { |
2055 | type = DeviceType::Fake; |
2056 | } else { |
2057 | ensureDev(VIDEO_DEV_NAME, &videoDev, nullptr); |
2058 | // Loopback prefs take precedence over fake prefs |
2059 | if (fakeByPref && videoDev.IsEmpty()) { |
2060 | type = DeviceType::Fake; |
2061 | } else { |
2062 | // For groupId correlation we need the audio device name. |
2063 | ensureDev(AUDIO_DEV_NAME, &audioDev, &audioDevRead); |
2064 | } |
2065 | } |
2066 | } |
2067 | videoParams = Some(VideoDeviceEnumerationParams(aVideoInputType, type, |
2068 | videoDev, audioDev)); |
2069 | } |
2070 | if (MediaEngineSource::IsAudio(aAudioInputType)) { |
2071 | nsAutoCString realAudioDev; |
2072 | DeviceType type = DeviceType::Real; |
2073 | if (aAudioInputType == MediaSourceEnum::Microphone) { |
2074 | // Fake and loopback devices are supported for only Microphone. |
2075 | if (forceFakes) { |
2076 | type = DeviceType::Fake; |
2077 | } else { |
2078 | ensureDev(AUDIO_DEV_NAME, &audioDev, &audioDevRead); |
2079 | // Loopback prefs take precedence over fake prefs |
2080 | if (fakeByPref && audioDev.IsEmpty()) { |
2081 | type = DeviceType::Fake; |
2082 | } else { |
2083 | realAudioDev = audioDev; |
2084 | } |
2085 | } |
2086 | } |
2087 | audioParams = |
2088 | Some(DeviceEnumerationParams(aAudioInputType, type, realAudioDev)); |
2089 | } |
2090 | return EnumerationParams(aFlags, videoParams, audioParams); |
2091 | } |
2092 | |
2093 | RefPtr<DeviceSetPromise> |
2094 | MediaManager::MaybeRequestPermissionAndEnumerateRawDevices( |
2095 | EnumerationParams aParams) { |
2096 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2096); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2096; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2097 | MOZ_ASSERT(aParams.mVideo.isSome() || aParams.mAudio.isSome() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2098); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)" ")"); do { *((volatile int*)__null) = 2098; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2098 | aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs))do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs ))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2098); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParams.mVideo.isSome() || aParams.mAudio.isSome() || aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)" ")"); do { *((volatile int*)__null) = 2098; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2099 | |
2100 | LOG("%s: aVideoInputType=%" PRIu8"u" ", aAudioInputType=%" PRIu8"u", __func__, |
2101 | static_cast<uint8_t>(aParams.VideoInputType()), |
2102 | static_cast<uint8_t>(aParams.AudioInputType())); |
2103 | |
2104 | if (sHasMainThreadShutdown) { |
2105 | // The media thread is no longer available but the result will not be |
2106 | // observable. |
2107 | return DeviceSetPromise::CreateAndResolve( |
2108 | new MediaDeviceSetRefCnt(), |
2109 | "MaybeRequestPermissionAndEnumerateRawDevices: sync shutdown"); |
2110 | } |
2111 | |
2112 | const bool hasVideo = aParams.mVideo.isSome(); |
2113 | const bool hasAudio = aParams.mAudio.isSome(); |
2114 | const bool hasAudioOutput = |
2115 | aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs); |
2116 | const bool hasFakeCams = aParams.HasFakeCams(); |
2117 | const bool hasFakeMics = aParams.HasFakeMics(); |
2118 | // True if at least one of video input or audio input is a real device |
2119 | // or there is audio output. |
2120 | const bool realDeviceRequested = (!hasFakeCams && hasVideo) || |
2121 | (!hasFakeMics && hasAudio) || hasAudioOutput; |
2122 | |
2123 | using NativePromise = |
2124 | MozPromise<CamerasAccessStatus, mozilla::ipc::ResponseRejectReason, |
2125 | /* IsExclusive = */ true>; |
2126 | RefPtr<NativePromise> deviceAccessPromise; |
2127 | if (realDeviceRequested && |
2128 | aParams.mFlags.contains(EnumerationFlag::AllowPermissionRequest) && |
2129 | Preferences::GetBool("media.navigator.permission.device", false)) { |
2130 | // Need to ask permission to retrieve list of all devices; |
2131 | // notify frontend observer and wait for callback notification to post |
2132 | // task. |
2133 | const char16_t* const type = |
2134 | (aParams.VideoInputType() != MediaSourceEnum::Camera) ? u"audio" |
2135 | : (aParams.AudioInputType() != MediaSourceEnum::Microphone) ? u"video" |
2136 | : u"all"; |
2137 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
2138 | DeviceAccessRequestPromiseHolderWithFallback deviceAccessPromiseHolder; |
2139 | deviceAccessPromise = deviceAccessPromiseHolder.Ensure(__func__); |
2140 | RefPtr task = NS_NewRunnableFunction( |
2141 | __func__, [holder = std::move(deviceAccessPromiseHolder)]() mutable { |
2142 | holder.Resolve(CamerasAccessStatus::Granted, |
2143 | "getUserMedia:got-device-permission"); |
2144 | }); |
2145 | obs->NotifyObservers(static_cast<nsIRunnable*>(task), |
2146 | "getUserMedia:ask-device-permission", type); |
2147 | } else if (realDeviceRequested && hasVideo && |
2148 | aParams.VideoInputType() == MediaSourceEnum::Camera) { |
2149 | ipc::PBackgroundChild* backgroundChild = |
2150 | ipc::BackgroundChild::GetOrCreateForCurrentThread(); |
2151 | deviceAccessPromise = backgroundChild->SendRequestCameraAccess( |
2152 | aParams.mFlags.contains(EnumerationFlag::AllowPermissionRequest)); |
2153 | } |
2154 | |
2155 | if (!deviceAccessPromise) { |
2156 | // No device access request needed. Proceed directly. |
2157 | deviceAccessPromise = |
2158 | NativePromise::CreateAndResolve(CamerasAccessStatus::Granted, __func__); |
2159 | } |
2160 | |
2161 | return deviceAccessPromise->Then( |
2162 | GetCurrentSerialEventTarget(), __func__, |
2163 | [this, self = RefPtr(this), aParams = std::move(aParams)]( |
2164 | NativePromise::ResolveOrRejectValue&& aValue) mutable { |
2165 | if (sHasMainThreadShutdown) { |
2166 | return DeviceSetPromise::CreateAndResolve( |
2167 | new MediaDeviceSetRefCnt(), |
2168 | "MaybeRequestPermissionAndEnumerateRawDevices: async shutdown"); |
2169 | } |
2170 | |
2171 | if (aValue.IsReject()) { |
2172 | // IPC failure probably means we're in shutdown. Resolve with |
2173 | // an empty set, so that callers do not need to handle rejection. |
2174 | return DeviceSetPromise::CreateAndResolve( |
2175 | new MediaDeviceSetRefCnt(), |
2176 | "MaybeRequestPermissionAndEnumerateRawDevices: ipc failure"); |
2177 | } |
2178 | |
2179 | if (auto v = aValue.ResolveValue(); |
2180 | v == CamerasAccessStatus::Error || |
2181 | v == CamerasAccessStatus::Rejected) { |
2182 | LOG("Request to camera access %s", |
2183 | v == CamerasAccessStatus::Rejected ? "was rejected" : "failed"); |
2184 | if (v == CamerasAccessStatus::Error) { |
2185 | NS_WARNING("Failed to request camera access")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to request camera access" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2185); |
2186 | } |
2187 | return DeviceSetPromise::CreateAndReject( |
2188 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
2189 | "MaybeRequestPermissionAndEnumerateRawDevices: camera access " |
2190 | "rejected"); |
2191 | } |
2192 | |
2193 | if (aParams.mFlags.contains(EnumerationFlag::AllowPermissionRequest)) { |
2194 | MOZ_ASSERT(aValue.ResolveValue() == CamerasAccessStatus::Granted)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aValue.ResolveValue() == CamerasAccessStatus::Granted )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aValue.ResolveValue() == CamerasAccessStatus::Granted ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aValue.ResolveValue() == CamerasAccessStatus::Granted", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aValue.ResolveValue() == CamerasAccessStatus::Granted" ")"); do { *((volatile int*)__null) = 2194; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2195 | EnsureNoPlaceholdersInDeviceCache(); |
2196 | } |
2197 | |
2198 | // We have to nest this, unfortunately, since we have no guarantees that |
2199 | // mMediaThread is alive. If we'd reject due to shutdown above, and have |
2200 | // the below async operation in a Then handler on the media thread the |
2201 | // Then handler would fail to dispatch and trip an assert on |
2202 | // destruction, for instance. |
2203 | return InvokeAsync( |
2204 | mMediaThread, __func__, [aParams = std::move(aParams)]() mutable { |
2205 | return DeviceSetPromise::CreateAndResolve( |
2206 | EnumerateRawDevices(std::move(aParams)), |
2207 | "MaybeRequestPermissionAndEnumerateRawDevices: success"); |
2208 | }); |
2209 | }); |
2210 | } |
2211 | |
2212 | /** |
2213 | * EnumerateRawDevices - Enumerate a list of audio & video devices that |
2214 | * satisfy passed-in constraints. List contains raw id's. |
2215 | */ |
2216 | |
2217 | /* static */ RefPtr<MediaManager::MediaDeviceSetRefCnt> |
2218 | MediaManager::EnumerateRawDevices(EnumerationParams aParams) { |
2219 | MOZ_ASSERT(IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 2219; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2220 | // Only enumerate what's asked for, and only fake cams and mics. |
2221 | RefPtr<MediaEngine> fakeBackend, realBackend; |
2222 | if (aParams.HasFakeCams() || aParams.HasFakeMics()) { |
2223 | fakeBackend = new MediaEngineFake(); |
2224 | } |
2225 | if (aParams.RealDeviceRequested()) { |
2226 | MediaManager* manager = MediaManager::GetIfExists(); |
2227 | MOZ_RELEASE_ASSERT(manager, "Must exist while media thread is alive")do { static_assert( mozilla::detail::AssertionConditionType< decltype(manager)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(manager))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("manager" " (" "Must exist while media thread is alive" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2227); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "manager" ") (" "Must exist while media thread is alive" ")"); do { *( (volatile int*)__null) = 2227; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
2228 | realBackend = manager->GetBackend(); |
2229 | } |
2230 | |
2231 | RefPtr<MediaEngine> videoBackend; |
2232 | RefPtr<MediaEngine> audioBackend; |
2233 | Maybe<MediaDeviceSet> micsOfVideoBackend; |
2234 | Maybe<MediaDeviceSet> speakers; |
2235 | RefPtr devices = new MediaDeviceSetRefCnt(); |
2236 | |
2237 | // Enumerate microphones first, then cameras, then speakers, since |
2238 | // the enumerateDevices() algorithm expects them listed in that order. |
2239 | if (const auto& audio = aParams.mAudio; audio.isSome()) { |
2240 | audioBackend = aParams.HasFakeMics() ? fakeBackend : realBackend; |
2241 | MediaDeviceSet audios; |
2242 | LOG("EnumerateRawDevices: Getting audio sources with %s backend", |
2243 | audioBackend == fakeBackend ? "fake" : "real"); |
2244 | GetMediaDevices(audioBackend, audio->mInputType, audios, |
2245 | audio->mForcedDeviceName.get()); |
2246 | if (audio->mInputType == MediaSourceEnum::Microphone && |
2247 | audioBackend == videoBackend) { |
2248 | micsOfVideoBackend.emplace(); |
2249 | micsOfVideoBackend->AppendElements(audios); |
2250 | } |
2251 | devices->AppendElements(std::move(audios)); |
2252 | } |
2253 | if (const auto& video = aParams.mVideo; video.isSome()) { |
2254 | videoBackend = aParams.HasFakeCams() ? fakeBackend : realBackend; |
2255 | MediaDeviceSet videos; |
2256 | LOG("EnumerateRawDevices: Getting video sources with %s backend", |
2257 | videoBackend == fakeBackend ? "fake" : "real"); |
2258 | GetMediaDevices(videoBackend, video->mInputType, videos, |
2259 | video->mForcedDeviceName.get()); |
2260 | devices->AppendElements(std::move(videos)); |
2261 | } |
2262 | if (aParams.mFlags.contains(EnumerationFlag::EnumerateAudioOutputs)) { |
2263 | MediaDeviceSet outputs; |
2264 | MOZ_ASSERT(realBackend)do { static_assert( mozilla::detail::AssertionConditionType< decltype(realBackend)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(realBackend))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("realBackend", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realBackend" ")"); do { *((volatile int*)__null) = 2264; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2265 | realBackend->EnumerateDevices(MediaSourceEnum::Other, |
2266 | MediaSinkEnum::Speaker, &outputs); |
2267 | speakers = Some(MediaDeviceSet()); |
2268 | speakers->AppendElements(outputs); |
2269 | devices->AppendElements(std::move(outputs)); |
2270 | } |
2271 | if (aParams.VideoInputType() == MediaSourceEnum::Camera) { |
2272 | MediaDeviceSet audios; |
2273 | LOG("EnumerateRawDevices: Getting audio sources with %s backend for " |
2274 | "groupId correlation", |
2275 | videoBackend == fakeBackend ? "fake" : "real"); |
2276 | // We need to correlate cameras with audio groupIds. We use the backend of |
2277 | // the camera to always do correlation on devices in the same scope. If we |
2278 | // don't do this, video-only getUserMedia will not apply groupId constraints |
2279 | // to the same set of groupIds as gets returned by enumerateDevices. |
2280 | if (micsOfVideoBackend.isSome()) { |
2281 | // Microphones from the same backend used for the cameras have |
2282 | // already been enumerated. Avoid doing it again. |
2283 | MOZ_ASSERT(aParams.mVideo->mForcedMicrophoneName ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParams.mVideo->mForcedMicrophoneName == aParams. mAudio->mForcedDeviceName)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2284); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName" ")"); do { *((volatile int*)__null) = 2284; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2284 | aParams.mAudio->mForcedDeviceName)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aParams.mVideo->mForcedMicrophoneName == aParams. mAudio->mForcedDeviceName)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2284); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParams.mVideo->mForcedMicrophoneName == aParams.mAudio->mForcedDeviceName" ")"); do { *((volatile int*)__null) = 2284; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2285 | audios.AppendElements(micsOfVideoBackend.extract()); |
2286 | } else { |
2287 | GetMediaDevices(videoBackend, MediaSourceEnum::Microphone, audios, |
2288 | aParams.mVideo->mForcedMicrophoneName.get()); |
2289 | } |
2290 | if (videoBackend == realBackend) { |
2291 | // When using the real backend for video, there could also be |
2292 | // speakers to correlate with. There are no fake speakers. |
2293 | if (speakers.isSome()) { |
2294 | // Speakers have already been enumerated. Avoid doing it again. |
2295 | audios.AppendElements(speakers.extract()); |
2296 | } else { |
2297 | realBackend->EnumerateDevices(MediaSourceEnum::Other, |
2298 | MediaSinkEnum::Speaker, &audios); |
2299 | } |
2300 | } |
2301 | GuessVideoDeviceGroupIDs(*devices, audios); |
2302 | } |
2303 | |
2304 | return devices; |
2305 | } |
2306 | |
2307 | RefPtr<ConstDeviceSetPromise> MediaManager::GetPhysicalDevices() { |
2308 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2308); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2308; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2309 | if (mPhysicalDevices) { |
2310 | return ConstDeviceSetPromise::CreateAndResolve(mPhysicalDevices, __func__); |
2311 | } |
2312 | if (mPendingDevicesPromises) { |
2313 | // Enumeration is already in progress. |
2314 | return mPendingDevicesPromises->AppendElement()->Ensure(__func__); |
2315 | } |
2316 | mPendingDevicesPromises = |
2317 | new Refcountable<nsTArray<MozPromiseHolder<ConstDeviceSetPromise>>>; |
2318 | MaybeRequestPermissionAndEnumerateRawDevices( |
2319 | CreateEnumerationParams(MediaSourceEnum::Camera, |
2320 | MediaSourceEnum::Microphone, |
2321 | EnumerationFlag::EnumerateAudioOutputs)) |
2322 | ->Then( |
2323 | GetCurrentSerialEventTarget(), __func__, |
2324 | [self = RefPtr(this), this, promises = mPendingDevicesPromises]( |
2325 | RefPtr<MediaDeviceSetRefCnt> aDevices) mutable { |
2326 | for (auto& promiseHolder : *promises) { |
2327 | promiseHolder.Resolve(aDevices, __func__); |
2328 | } |
2329 | // mPendingDevicesPromises may have changed if devices have changed. |
2330 | if (promises == mPendingDevicesPromises) { |
2331 | mPendingDevicesPromises = nullptr; |
2332 | mPhysicalDevices = std::move(aDevices); |
2333 | } |
2334 | }, |
2335 | [](RefPtr<MediaMgrError>&& reason) { |
2336 | MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "MaybeRequestPermissionAndEnumerateRawDevices does not reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "MaybeRequestPermissionAndEnumerateRawDevices does not reject" ")"); do { *((volatile int*)__null) = 2337; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2337 | "MaybeRequestPermissionAndEnumerateRawDevices does not reject")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "MaybeRequestPermissionAndEnumerateRawDevices does not reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "MaybeRequestPermissionAndEnumerateRawDevices does not reject" ")"); do { *((volatile int*)__null) = 2337; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2338 | }); |
2339 | |
2340 | return mPendingDevicesPromises->AppendElement()->Ensure(__func__); |
2341 | } |
2342 | |
2343 | MediaManager::MediaManager(already_AddRefed<TaskQueue> aMediaThread) |
2344 | : mMediaThread(aMediaThread), mBackend(nullptr) { |
2345 | mPrefs.mFreq = 1000; // 1KHz test tone |
2346 | mPrefs.mWidth = 0; // adaptive default |
2347 | mPrefs.mHeight = 0; // adaptive default |
2348 | mPrefs.mFPS = MediaEnginePrefs::DEFAULT_VIDEO_FPS; |
2349 | mPrefs.mUsePlatformProcessing = false; |
2350 | mPrefs.mAecOn = false; |
2351 | mPrefs.mUseAecMobile = false; |
2352 | mPrefs.mAgcOn = false; |
2353 | mPrefs.mHPFOn = false; |
2354 | mPrefs.mNoiseOn = false; |
2355 | mPrefs.mTransientOn = false; |
2356 | mPrefs.mAgc2Forced = false; |
2357 | mPrefs.mExpectDrift = -1; // auto |
2358 | #ifdef MOZ_WEBRTC1 |
2359 | mPrefs.mAgc = |
2360 | webrtc::AudioProcessing::Config::GainController1::Mode::kAdaptiveDigital; |
2361 | mPrefs.mNoise = |
2362 | webrtc::AudioProcessing::Config::NoiseSuppression::Level::kModerate; |
2363 | #else |
2364 | mPrefs.mAgc = 0; |
2365 | mPrefs.mNoise = 0; |
2366 | #endif |
2367 | mPrefs.mChannels = 0; // max channels default |
2368 | nsresult rv; |
2369 | nsCOMPtr<nsIPrefService> prefs = |
2370 | do_GetService("@mozilla.org/preferences-service;1", &rv); |
2371 | if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) { |
2372 | nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs); |
2373 | if (branch) { |
2374 | GetPrefs(branch, nullptr); |
2375 | } |
2376 | } |
2377 | } |
2378 | |
2379 | 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" , 2380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 2380; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 2380; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("MediaManager" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("MediaManager" ), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType MediaManager::Release(void) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(int32_t(mRefCnt) > 0) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 2380 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 2380; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("MediaManager" " not thread-safe"); const char * const nametmp = "MediaManager"; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult MediaManager::QueryInterface(const nsIID& aIID, void** aInstancePtr ) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2380); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(3 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<MediaManager, nsIMediaManagerService> , int32_t( reinterpret_cast<char*>(static_cast<nsIMediaManagerService *>((MediaManager*)0x1000)) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID <MediaManager, nsIMemoryReporter>, int32_t( reinterpret_cast <char*>(static_cast<nsIMemoryReporter*>((MediaManager *)0x1000)) - reinterpret_cast<char*>((MediaManager*)0x1000 ))}, {&mozilla::detail::kImplementedIID<MediaManager, nsIObserver >, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver *>((MediaManager*)0x1000)) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID <MediaManager, nsISupports>, int32_t(reinterpret_cast< char*>(static_cast<nsISupports*>( static_cast<nsIMediaManagerService *>((MediaManager*)0x1000))) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, { nullptr, 0 } } ; static_assert(( sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface" ); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID , aInstancePtr, table); return rv; } |
2380 | nsIObserver)MozExternalRefCountType MediaManager::AddRef(void) { static_assert (!std::is_destructible_v<MediaManager>, "Reference-counted class " "MediaManager" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { *((volatile int*)__null) = 2380; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 2380; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("MediaManager" " not thread-safe"); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("MediaManager" ), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType MediaManager::Release(void) { do { static_assert( mozilla::detail ::AssertionConditionType<decltype(int32_t(mRefCnt) > 0) >::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { *((volatile int*)__null) = 2380 ; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("MediaManager" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("MediaManager" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"MediaManager\" != nullptr" " (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"MediaManager\" != nullptr" ") (" "Must specify a name" ")"); do { *((volatile int*)__null ) = 2380; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread .AssertOwnership("MediaManager" " not thread-safe"); const char * const nametmp = "MediaManager"; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult MediaManager::QueryInterface(const nsIID& aIID, void** aInstancePtr ) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "QueryInterface requires a non-NULL destination!", "aInstancePtr" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2380); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(3 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<MediaManager, nsIMediaManagerService> , int32_t( reinterpret_cast<char*>(static_cast<nsIMediaManagerService *>((MediaManager*)0x1000)) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID <MediaManager, nsIMemoryReporter>, int32_t( reinterpret_cast <char*>(static_cast<nsIMemoryReporter*>((MediaManager *)0x1000)) - reinterpret_cast<char*>((MediaManager*)0x1000 ))}, {&mozilla::detail::kImplementedIID<MediaManager, nsIObserver >, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver *>((MediaManager*)0x1000)) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, {&mozilla::detail::kImplementedIID <MediaManager, nsISupports>, int32_t(reinterpret_cast< char*>(static_cast<nsISupports*>( static_cast<nsIMediaManagerService *>((MediaManager*)0x1000))) - reinterpret_cast<char*> ((MediaManager*)0x1000))}, { nullptr, 0 } } ; static_assert(( sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface" ); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID , aInstancePtr, table); return rv; } |
2381 | |
2382 | /* static */ |
2383 | StaticRefPtr<MediaManager> MediaManager::sSingleton; |
2384 | |
2385 | #ifdef DEBUG1 |
2386 | /* static */ |
2387 | bool MediaManager::IsInMediaThread() { |
2388 | return sSingleton && sSingleton->mMediaThread->IsOnCurrentThread(); |
2389 | } |
2390 | #endif |
2391 | |
2392 | template <typename Function> |
2393 | static void ForeachObservedPref(const Function& aFunction) { |
2394 | aFunction("media.navigator.video.default_width"_ns); |
2395 | aFunction("media.navigator.video.default_height"_ns); |
2396 | aFunction("media.navigator.video.default_fps"_ns); |
2397 | aFunction("media.navigator.audio.fake_frequency"_ns); |
2398 | aFunction("media.audio_loopback_dev"_ns); |
2399 | aFunction("media.video_loopback_dev"_ns); |
2400 | aFunction("media.getusermedia.fake-camera-name"_ns); |
2401 | #ifdef MOZ_WEBRTC1 |
2402 | aFunction("media.getusermedia.audio.processing.aec.enabled"_ns); |
2403 | aFunction("media.getusermedia.audio.processing.aec"_ns); |
2404 | aFunction("media.getusermedia.audio.processing.agc.enabled"_ns); |
2405 | aFunction("media.getusermedia.audio.processing.agc"_ns); |
2406 | aFunction("media.getusermedia.audio.processing.hpf.enabled"_ns); |
2407 | aFunction("media.getusermedia.audio.processing.noise.enabled"_ns); |
2408 | aFunction("media.getusermedia.audio.processing.noise"_ns); |
2409 | aFunction("media.getusermedia.audio.max_channels"_ns); |
2410 | aFunction("media.navigator.streams.fake"_ns); |
2411 | #endif |
2412 | } |
2413 | |
2414 | // NOTE: never NS_DispatchAndSpinEventLoopUntilComplete to the MediaManager |
2415 | // thread from the MainThread, as we NS_DispatchAndSpinEventLoopUntilComplete to |
2416 | // MainThread from MediaManager thread. |
2417 | |
2418 | // Guaranteed never to return nullptr. |
2419 | /* static */ |
2420 | MediaManager* MediaManager::Get() { |
2421 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2421; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2422 | |
2423 | if (!sSingleton) { |
2424 | static int timesCreated = 0; |
2425 | timesCreated++; |
2426 | MOZ_RELEASE_ASSERT(timesCreated == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(timesCreated == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(timesCreated == 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("timesCreated == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2426); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "timesCreated == 1" ")"); do { *((volatile int*)__null) = 2426; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2427 | |
2428 | RefPtr<TaskQueue> mediaThread = TaskQueue::Create( |
2429 | GetMediaThreadPool(MediaThreadType::SUPERVISOR), "MediaManager"); |
2430 | LOG("New Media thread for gum"); |
2431 | |
2432 | sSingleton = new MediaManager(mediaThread.forget()); |
2433 | |
2434 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
2435 | if (obs) { |
2436 | obs->AddObserver(sSingleton, "last-pb-context-exited", false); |
2437 | obs->AddObserver(sSingleton, "getUserMedia:got-device-permission", false); |
2438 | obs->AddObserver(sSingleton, "getUserMedia:privileged:allow", false); |
2439 | obs->AddObserver(sSingleton, "getUserMedia:response:allow", false); |
2440 | obs->AddObserver(sSingleton, "getUserMedia:response:deny", false); |
2441 | obs->AddObserver(sSingleton, "getUserMedia:response:noOSPermission", |
2442 | false); |
2443 | obs->AddObserver(sSingleton, "getUserMedia:revoke", false); |
2444 | obs->AddObserver(sSingleton, "getUserMedia:muteVideo", false); |
2445 | obs->AddObserver(sSingleton, "getUserMedia:unmuteVideo", false); |
2446 | obs->AddObserver(sSingleton, "getUserMedia:muteAudio", false); |
2447 | obs->AddObserver(sSingleton, "getUserMedia:unmuteAudio", false); |
2448 | obs->AddObserver(sSingleton, "application-background", false); |
2449 | obs->AddObserver(sSingleton, "application-foreground", false); |
2450 | } |
2451 | // else MediaManager won't work properly and will leak (see bug 837874) |
2452 | nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1"); |
2453 | if (prefs) { |
2454 | ForeachObservedPref([&](const nsLiteralCString& aPrefName) { |
2455 | prefs->AddObserver(aPrefName, sSingleton, false); |
2456 | }); |
2457 | } |
2458 | RegisterStrongMemoryReporter(sSingleton); |
2459 | |
2460 | // Prepare async shutdown |
2461 | |
2462 | class Blocker : public media::ShutdownBlocker { |
2463 | public: |
2464 | Blocker() |
2465 | : media::ShutdownBlocker( |
2466 | u"Media shutdown: blocking on media thread"_ns) {} |
2467 | |
2468 | NS_IMETHODvirtual nsresult BlockShutdown(nsIAsyncShutdownClient*) override { |
2469 | MOZ_RELEASE_ASSERT(MediaManager::GetIfExists())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::GetIfExists())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::GetIfExists()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("MediaManager::GetIfExists()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2469); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "MediaManager::GetIfExists()" ")"); do { *((volatile int*)__null) = 2469; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2470 | MediaManager::GetIfExists()->Shutdown(); |
2471 | return NS_OK; |
2472 | } |
2473 | }; |
2474 | |
2475 | sSingleton->mShutdownBlocker = new Blocker(); |
2476 | nsresult rv = media::MustGetShutdownBarrier()->AddBlocker( |
2477 | sSingleton->mShutdownBlocker, NS_LITERAL_STRING_FROM_CSTRING(__FILE__)static_cast<const nsLiteralString&>( nsLiteralString (u"" "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" )), |
2478 | __LINE__2478, u""_ns); |
2479 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2479); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 2479; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2480 | } |
2481 | return sSingleton; |
2482 | } |
2483 | |
2484 | /* static */ |
2485 | MediaManager* MediaManager::GetIfExists() { |
2486 | MOZ_ASSERT(NS_IsMainThread() || IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread() || IsInMediaThread())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(NS_IsMainThread() || IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread() || IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2486); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread() || IsInMediaThread()" ")"); do { *((volatile int*)__null) = 2486; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2487 | return sSingleton; |
2488 | } |
2489 | |
2490 | /* static */ |
2491 | already_AddRefed<MediaManager> MediaManager::GetInstance() { |
2492 | // so we can have non-refcounted getters |
2493 | RefPtr<MediaManager> service = MediaManager::Get(); |
2494 | return service.forget(); |
2495 | } |
2496 | |
2497 | media::Parent<media::NonE10s>* MediaManager::GetNonE10sParent() { |
2498 | if (!mNonE10sParent) { |
2499 | mNonE10sParent = new media::Parent<media::NonE10s>(); |
2500 | } |
2501 | return mNonE10sParent; |
2502 | } |
2503 | |
2504 | /* static */ |
2505 | void MediaManager::Dispatch(already_AddRefed<Runnable> task) { |
2506 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2506; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2507 | if (sHasMainThreadShutdown) { |
2508 | // Can't safely delete task here since it may have items with specific |
2509 | // thread-release requirements. |
2510 | // XXXkhuey well then who is supposed to delete it?! We don't signal |
2511 | // that we failed ... |
2512 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2512); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 2512; __attribute__((nomerge)) ::abort(); } while (false); } while (false); |
2513 | return; |
2514 | } |
2515 | NS_ASSERTION(Get(), "MediaManager singleton?")do { if (!(Get())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "MediaManager singleton?" , "Get()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2515); MOZ_PretendNoReturn(); } } while (0); |
2516 | NS_ASSERTION(Get()->mMediaThread, "No thread yet")do { if (!(Get()->mMediaThread)) { NS_DebugBreak(NS_DEBUG_ASSERTION , "No thread yet", "Get()->mMediaThread", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2516); MOZ_PretendNoReturn(); } } while (0); |
2517 | MOZ_ALWAYS_SUCCEEDS(Get()->mMediaThread->Dispatch(std::move(task)))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (Get()->mMediaThread->Dispatch(std::move(task)))), 1))) ), 1))) { } else { do { static_assert( mozilla::detail::AssertionConditionType <decltype(false)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(Get()->mMediaThread->Dispatch(std::move(task)))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2517); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(Get()->mMediaThread->Dispatch(std::move(task)))" ")"); do { *((volatile int*)__null) = 2517; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2518 | } |
2519 | |
2520 | template <typename MozPromiseType, typename FunctionType> |
2521 | /* static */ |
2522 | RefPtr<MozPromiseType> MediaManager::Dispatch(StaticString aName, |
2523 | FunctionType&& aFunction) { |
2524 | MozPromiseHolder<MozPromiseType> holder; |
2525 | RefPtr<MozPromiseType> promise = holder.Ensure(aName); |
2526 | MediaManager::Dispatch(NS_NewRunnableFunction( |
2527 | aName, [h = std::move(holder), func = std::forward<FunctionType>( |
2528 | aFunction)]() mutable { func(h); })); |
2529 | return promise; |
2530 | } |
2531 | |
2532 | /* static */ |
2533 | nsresult MediaManager::NotifyRecordingStatusChange( |
2534 | nsPIDOMWindowInner* aWindow) { |
2535 | NS_ENSURE_ARG(aWindow)do { if ((__builtin_expect(!!(!(aWindow)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWindow" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2535); return NS_ERROR_INVALID_ARG; } } while (false); |
2536 | |
2537 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
2538 | if (!obs) { |
2539 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Could not get the Observer service for GetUserMedia recording " "notification.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2541) |
2540 | "Could not get the Observer service for GetUserMedia recording "NS_DebugBreak(NS_DEBUG_WARNING, "Could not get the Observer service for GetUserMedia recording " "notification.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2541) |
2541 | "notification.")NS_DebugBreak(NS_DEBUG_WARNING, "Could not get the Observer service for GetUserMedia recording " "notification.", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2541); |
2542 | return NS_ERROR_FAILURE; |
2543 | } |
2544 | |
2545 | auto props = MakeRefPtr<nsHashPropertyBag>(); |
2546 | |
2547 | nsCString pageURL; |
2548 | nsCOMPtr<nsIURI> docURI = aWindow->GetDocumentURI(); |
2549 | NS_ENSURE_TRUE(docURI, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(docURI)), 0))) { NS_DebugBreak (NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "docURI" ") failed", nullptr , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2549); return NS_ERROR_FAILURE; } } while (false); |
2550 | |
2551 | nsresult rv = docURI->GetSpec(pageURL); |
2552 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2552); return rv; } } while (false); |
2553 | |
2554 | NS_ConvertUTF8toUTF16 requestURL(pageURL); |
2555 | |
2556 | props->SetPropertyAsAString(u"requestURL"_ns, requestURL); |
2557 | props->SetPropertyAsInterface(u"window"_ns, aWindow); |
2558 | |
2559 | obs->NotifyObservers(static_cast<nsIPropertyBag2*>(props), |
2560 | "recording-device-events", nullptr); |
2561 | LOG("Sent recording-device-events for url '%s'", pageURL.get()); |
2562 | |
2563 | return NS_OK; |
2564 | } |
2565 | |
2566 | void MediaManager::DeviceListChanged() { |
2567 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2567); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2567; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2568 | if (sHasMainThreadShutdown) { |
2569 | return; |
2570 | } |
2571 | // Invalidate immediately to provide an up-to-date device list for future |
2572 | // enumerations on platforms with sane device-list-changed events. |
2573 | InvalidateDeviceCache(); |
2574 | |
2575 | // Wait 200 ms, because |
2576 | // A) on some Windows machines, if we call EnumerateRawDevices immediately |
2577 | // after receiving devicechange event, we'd get an outdated devices list. |
2578 | // B) Waiting helps coalesce multiple calls on us into one, which can happen |
2579 | // if a device with both audio input and output is attached or removed. |
2580 | // We want to react & fire a devicechange event only once in that case. |
2581 | |
2582 | // The wait is extended if another hardware device-list-changed notification |
2583 | // is received to provide the full 200ms for EnumerateRawDevices(). |
2584 | if (mDeviceChangeTimer) { |
2585 | mDeviceChangeTimer->Cancel(); |
2586 | } else { |
2587 | mDeviceChangeTimer = MakeRefPtr<MediaTimer>(); |
2588 | } |
2589 | // However, if this would cause a delay of over 1000ms in handling the |
2590 | // oldest unhandled event, then respond now and set the timer to run |
2591 | // EnumerateRawDevices() again in 200ms. |
2592 | auto now = TimeStamp::NowLoRes(); |
2593 | auto enumerateDelay = TimeDuration::FromMilliseconds(200); |
2594 | auto coalescenceLimit = TimeDuration::FromMilliseconds(1000) - enumerateDelay; |
2595 | if (!mUnhandledDeviceChangeTime) { |
2596 | mUnhandledDeviceChangeTime = now; |
2597 | } else if (now - mUnhandledDeviceChangeTime > coalescenceLimit) { |
2598 | HandleDeviceListChanged(); |
2599 | mUnhandledDeviceChangeTime = now; |
2600 | } |
2601 | RefPtr<MediaManager> self = this; |
2602 | mDeviceChangeTimer->WaitFor(enumerateDelay, __func__) |
2603 | ->Then( |
2604 | GetCurrentSerialEventTarget(), __func__, |
2605 | [self, this] { |
2606 | // Invalidate again for the sake of platforms with inconsistent |
2607 | // timing between device-list-changed notification and enumeration. |
2608 | InvalidateDeviceCache(); |
2609 | |
2610 | mUnhandledDeviceChangeTime = TimeStamp(); |
2611 | HandleDeviceListChanged(); |
2612 | }, |
2613 | [] { /* Timer was canceled by us, or we're in shutdown. */ }); |
2614 | } |
2615 | |
2616 | void MediaManager::EnsureNoPlaceholdersInDeviceCache() { |
2617 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2617; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2618 | |
2619 | if (mPhysicalDevices) { |
2620 | // Invalidate the list if there is a placeholder |
2621 | for (const auto& device : *mPhysicalDevices) { |
2622 | if (device->mIsPlaceholder) { |
2623 | InvalidateDeviceCache(); |
2624 | break; |
2625 | } |
2626 | } |
2627 | } |
2628 | } |
2629 | |
2630 | void MediaManager::InvalidateDeviceCache() { |
2631 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2631; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2632 | |
2633 | mPhysicalDevices = nullptr; |
2634 | // Disconnect any in-progress enumeration, which may now be out of date, |
2635 | // from updating mPhysicalDevices or resolving future device request |
2636 | // promises. |
2637 | mPendingDevicesPromises = nullptr; |
2638 | } |
2639 | |
2640 | void MediaManager::HandleDeviceListChanged() { |
2641 | mDeviceListChangeEvent.Notify(); |
2642 | |
2643 | GetPhysicalDevices()->Then( |
2644 | GetCurrentSerialEventTarget(), __func__, |
2645 | [self = RefPtr(this), this](RefPtr<const MediaDeviceSetRefCnt> aDevices) { |
2646 | if (!MediaManager::GetIfExists()) { |
2647 | return; |
2648 | } |
2649 | |
2650 | nsTHashSet<nsString> deviceIDs; |
2651 | for (const auto& device : *aDevices) { |
2652 | deviceIDs.Insert(device->mRawID); |
2653 | } |
2654 | // For any real removed cameras or microphones, notify their |
2655 | // listeners cleanly that the source has stopped, so JS knows and |
2656 | // usage indicators update. |
2657 | // First collect the listeners in an array to stop them after |
2658 | // iterating the hashtable. The StopRawID() method indirectly |
2659 | // modifies the mActiveWindows and would assert-crash if the |
2660 | // iterator were active while the table is being enumerated. |
2661 | const auto windowListeners = ToArray(mActiveWindows.Values()); |
2662 | for (const RefPtr<GetUserMediaWindowListener>& l : windowListeners) { |
2663 | const auto activeDevices = l->GetDevices(); |
2664 | for (const RefPtr<LocalMediaDevice>& device : *activeDevices) { |
2665 | if (device->IsFake()) { |
2666 | continue; |
2667 | } |
2668 | MediaSourceEnum mediaSource = device->GetMediaSource(); |
2669 | if (mediaSource != MediaSourceEnum::Microphone && |
2670 | mediaSource != MediaSourceEnum::Camera) { |
2671 | continue; |
2672 | } |
2673 | if (!deviceIDs.Contains(device->RawID())) { |
2674 | // Device has been removed |
2675 | l->StopRawID(device->RawID()); |
2676 | } |
2677 | } |
2678 | } |
2679 | }, |
2680 | [](RefPtr<MediaMgrError>&& reason) { |
2681 | MOZ_ASSERT_UNREACHABLE("EnumerateRawDevices does not reject")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "EnumerateRawDevices does not reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "EnumerateRawDevices does not reject" ")"); do { *((volatile int*)__null) = 2681; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2682 | }); |
2683 | } |
2684 | |
2685 | size_t MediaManager::AddTaskAndGetCount(uint64_t aWindowID, |
2686 | const nsAString& aCallID, |
2687 | RefPtr<GetUserMediaTask> aTask) { |
2688 | // Store the task w/callbacks. |
2689 | mActiveCallbacks.InsertOrUpdate(aCallID, std::move(aTask)); |
2690 | |
2691 | // Add a WindowID cross-reference so OnNavigation can tear things down |
2692 | nsTArray<nsString>* const array = mCallIds.GetOrInsertNew(aWindowID); |
2693 | array->AppendElement(aCallID); |
2694 | |
2695 | return array->Length(); |
2696 | } |
2697 | |
2698 | RefPtr<GetUserMediaTask> MediaManager::TakeGetUserMediaTask( |
2699 | const nsAString& aCallID) { |
2700 | RefPtr<GetUserMediaTask> task; |
2701 | mActiveCallbacks.Remove(aCallID, getter_AddRefs(task)); |
2702 | if (!task) { |
2703 | return nullptr; |
2704 | } |
2705 | nsTArray<nsString>* array; |
2706 | mCallIds.Get(task->GetWindowID(), &array); |
2707 | MOZ_ASSERT(array)do { static_assert( mozilla::detail::AssertionConditionType< decltype(array)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(array))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("array", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "array" ")") ; do { *((volatile int*)__null) = 2707; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2708 | array->RemoveElement(aCallID); |
2709 | return task; |
2710 | } |
2711 | |
2712 | void MediaManager::NotifyAllowed(const nsString& aCallID, |
2713 | const LocalMediaDeviceSet& aDevices) { |
2714 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
2715 | nsCOMPtr<nsIMutableArray> devicesCopy = nsArray::Create(); |
2716 | for (const auto& device : aDevices) { |
2717 | nsresult rv = devicesCopy->AppendElement(device); |
2718 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2718)) { |
2719 | obs->NotifyObservers(nullptr, "getUserMedia:response:deny", |
2720 | aCallID.get()); |
2721 | return; |
2722 | } |
2723 | } |
2724 | obs->NotifyObservers(devicesCopy, "getUserMedia:privileged:allow", |
2725 | aCallID.get()); |
2726 | } |
2727 | |
2728 | nsresult MediaManager::GenerateUUID(nsAString& aResult) { |
2729 | nsresult rv; |
2730 | nsCOMPtr<nsIUUIDGenerator> uuidgen = |
2731 | do_GetService("@mozilla.org/uuid-generator;1", &rv); |
2732 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2732); return rv; } } while (false); |
2733 | |
2734 | // Generate a call ID. |
2735 | nsID id; |
2736 | rv = uuidgen->GenerateUUIDInPlace(&id); |
2737 | NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl (__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName (__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t >(__rv), name ? " (" : "", name ? name : "", name ? ")" : "" ); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2737); return rv; } } while (false); |
2738 | |
2739 | char buffer[NSID_LENGTH39]; |
2740 | id.ToProvidedString(buffer); |
2741 | aResult.Assign(NS_ConvertUTF8toUTF16(buffer)); |
2742 | return NS_OK; |
2743 | } |
2744 | |
2745 | enum class GetUserMediaSecurityState { |
2746 | Other = 0, |
2747 | HTTPS = 1, |
2748 | File = 2, |
2749 | App = 3, |
2750 | Localhost = 4, |
2751 | Loop = 5, |
2752 | Privileged = 6 |
2753 | }; |
2754 | |
2755 | /** |
2756 | * This function is used in getUserMedia when privacy.resistFingerprinting is |
2757 | * true. Only mediaSource of audio/video constraint will be kept. |
2758 | */ |
2759 | static void ReduceConstraint( |
2760 | OwningBooleanOrMediaTrackConstraints& aConstraint) { |
2761 | // Not requesting stream. |
2762 | if (!MediaManager::IsOn(aConstraint)) { |
2763 | return; |
2764 | } |
2765 | |
2766 | // It looks like {audio: true}, do nothing. |
2767 | if (!aConstraint.IsMediaTrackConstraints()) { |
2768 | return; |
2769 | } |
2770 | |
2771 | // Keep mediaSource, ignore all other constraints. |
2772 | Maybe<nsString> mediaSource; |
2773 | if (aConstraint.GetAsMediaTrackConstraints().mMediaSource.WasPassed()) { |
2774 | mediaSource = |
2775 | Some(aConstraint.GetAsMediaTrackConstraints().mMediaSource.Value()); |
2776 | } |
2777 | aConstraint.Uninit(); |
2778 | if (mediaSource) { |
2779 | aConstraint.SetAsMediaTrackConstraints().mMediaSource.Construct( |
2780 | *mediaSource); |
2781 | } else { |
2782 | Unused << aConstraint.SetAsMediaTrackConstraints(); |
2783 | } |
2784 | } |
2785 | |
2786 | /** |
2787 | * The entry point for this file. A call from Navigator::mozGetUserMedia |
2788 | * will end up here. MediaManager is a singleton that is responsible |
2789 | * for handling all incoming getUserMedia calls from every window. |
2790 | */ |
2791 | RefPtr<MediaManager::StreamPromise> MediaManager::GetUserMedia( |
2792 | nsPIDOMWindowInner* aWindow, |
2793 | const MediaStreamConstraints& aConstraintsPassedIn, |
2794 | CallerType aCallerType) { |
2795 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 2795; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2796 | MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWindow)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")" ); do { *((volatile int*)__null) = 2796; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2797 | uint64_t windowID = aWindow->WindowID(); |
2798 | |
2799 | MediaStreamConstraints c(aConstraintsPassedIn); // use a modifiable copy |
2800 | |
2801 | if (sHasMainThreadShutdown) { |
2802 | return StreamPromise::CreateAndReject( |
2803 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError, |
2804 | "In shutdown"), |
2805 | __func__); |
2806 | } |
2807 | |
2808 | // Determine permissions early (while we still have a stack). |
2809 | |
2810 | nsIURI* docURI = aWindow->GetDocumentURI(); |
2811 | if (!docURI) { |
2812 | return StreamPromise::CreateAndReject( |
2813 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), __func__); |
2814 | } |
2815 | bool isChrome = (aCallerType == CallerType::System); |
2816 | bool privileged = |
2817 | isChrome || |
2818 | Preferences::GetBool("media.navigator.permission.disabled", false); |
2819 | bool isSecure = aWindow->IsSecureContext(); |
2820 | bool isHandlingUserInput = UserActivation::IsHandlingUserInput(); |
2821 | nsCString host; |
2822 | nsresult rv = docURI->GetHost(host); |
Value stored to 'rv' during its initialization is never read | |
2823 | |
2824 | nsCOMPtr<nsIPrincipal> principal = |
2825 | nsGlobalWindowInner::Cast(aWindow)->GetPrincipal(); |
2826 | if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2826)) { |
2827 | return StreamPromise::CreateAndReject( |
2828 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
2829 | __func__); |
2830 | } |
2831 | |
2832 | Document* doc = aWindow->GetExtantDoc(); |
2833 | if (NS_WARN_IF(!doc)NS_warn_if_impl(!doc, "!doc", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2833)) { |
2834 | return StreamPromise::CreateAndReject( |
2835 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
2836 | __func__); |
2837 | } |
2838 | |
2839 | // Disallow access to null principal pages and http pages (unless pref) |
2840 | if (principal->GetIsNullPrincipal() || |
2841 | !(isSecure || StaticPrefs::media_getusermedia_insecure_enabled())) { |
2842 | return StreamPromise::CreateAndReject( |
2843 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
2844 | __func__); |
2845 | } |
2846 | |
2847 | // This principal needs to be sent to different threads and so via IPC. |
2848 | // For this reason it's better to convert it to PrincipalInfo right now. |
2849 | ipc::PrincipalInfo principalInfo; |
2850 | rv = PrincipalToPrincipalInfo(principal, &principalInfo); |
2851 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 2851)) { |
2852 | return StreamPromise::CreateAndReject( |
2853 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
2854 | __func__); |
2855 | } |
2856 | |
2857 | const bool resistFingerprinting = |
2858 | !isChrome && doc->ShouldResistFingerprinting(RFPTarget::MediaDevices); |
2859 | if (resistFingerprinting) { |
2860 | ReduceConstraint(c.mVideo); |
2861 | ReduceConstraint(c.mAudio); |
2862 | } |
2863 | |
2864 | if (!Preferences::GetBool("media.navigator.video.enabled", true)) { |
2865 | c.mVideo.SetAsBoolean() = false; |
2866 | } |
2867 | |
2868 | MediaSourceEnum videoType = MediaSourceEnum::Other; // none |
2869 | MediaSourceEnum audioType = MediaSourceEnum::Other; // none |
2870 | |
2871 | if (c.mVideo.IsMediaTrackConstraints()) { |
2872 | auto& vc = c.mVideo.GetAsMediaTrackConstraints(); |
2873 | if (!vc.mMediaSource.WasPassed()) { |
2874 | vc.mMediaSource.Construct().AssignASCII( |
2875 | dom::GetEnumString(MediaSourceEnum::Camera)); |
2876 | } |
2877 | videoType = dom::StringToEnum<MediaSourceEnum>(vc.mMediaSource.Value()) |
2878 | .valueOr(MediaSourceEnum::Other); |
2879 | Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE, |
2880 | (uint32_t)videoType); |
2881 | switch (videoType) { |
2882 | case MediaSourceEnum::Camera: |
2883 | break; |
2884 | |
2885 | case MediaSourceEnum::Browser: |
2886 | // If no window id is passed in then default to the caller's window. |
2887 | // Functional defaults are helpful in tests, but also a natural outcome |
2888 | // of the constraints API's limited semantics for requiring input. |
2889 | if (!vc.mBrowserWindow.WasPassed()) { |
2890 | nsPIDOMWindowOuter* outer = aWindow->GetOuterWindow(); |
2891 | vc.mBrowserWindow.Construct(outer->WindowID()); |
2892 | } |
2893 | [[fallthrough]]; |
2894 | case MediaSourceEnum::Screen: |
2895 | case MediaSourceEnum::Window: |
2896 | // Deny screensharing request if support is disabled, or |
2897 | // the requesting document is not from a host on the whitelist. |
2898 | if (!Preferences::GetBool( |
2899 | ((videoType == MediaSourceEnum::Browser) |
2900 | ? "media.getusermedia.browser.enabled" |
2901 | : "media.getusermedia.screensharing.enabled"), |
2902 | false) || |
2903 | (!privileged && !aWindow->IsSecureContext())) { |
2904 | return StreamPromise::CreateAndReject( |
2905 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
2906 | __func__); |
2907 | } |
2908 | break; |
2909 | |
2910 | case MediaSourceEnum::Microphone: |
2911 | case MediaSourceEnum::Other: |
2912 | default: { |
2913 | return StreamPromise::CreateAndReject( |
2914 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::OverconstrainedError, |
2915 | "", u"mediaSource"_ns), |
2916 | __func__); |
2917 | } |
2918 | } |
2919 | |
2920 | if (!privileged) { |
2921 | // Only allow privileged content to explicitly pick full-screen, |
2922 | // application or tabsharing, since these modes are still available for |
2923 | // testing. All others get "Window" (*) sharing. |
2924 | // |
2925 | // *) We overload "Window" with the new default getDisplayMedia spec- |
2926 | // mandated behavior of not influencing user-choice, which we currently |
2927 | // implement as a list containing BOTH windows AND screen(s). |
2928 | // |
2929 | // Notes on why we chose "Window" as the one to overload. Two reasons: |
2930 | // |
2931 | // 1. It's the closest logically & behaviorally (multi-choice, no default) |
2932 | // 2. Screen is still useful in tests (implicit default is entire screen) |
2933 | // |
2934 | // For UX reasons we don't want "Entire Screen" to be the first/default |
2935 | // choice (in our code first=default). It's a "scary" source that comes |
2936 | // with complicated warnings on-top that would be confusing as the first |
2937 | // thing people see, and also deserves to be listed as last resort for |
2938 | // privacy reasons. |
2939 | |
2940 | if (videoType == MediaSourceEnum::Screen || |
2941 | videoType == MediaSourceEnum::Browser) { |
2942 | videoType = MediaSourceEnum::Window; |
2943 | vc.mMediaSource.Value().AssignASCII(dom::GetEnumString(videoType)); |
2944 | } |
2945 | // only allow privileged content to set the window id |
2946 | if (vc.mBrowserWindow.WasPassed()) { |
2947 | vc.mBrowserWindow.Value() = -1; |
2948 | } |
2949 | if (vc.mAdvanced.WasPassed()) { |
2950 | for (MediaTrackConstraintSet& cs : vc.mAdvanced.Value()) { |
2951 | if (cs.mBrowserWindow.WasPassed()) { |
2952 | cs.mBrowserWindow.Value() = -1; |
2953 | } |
2954 | } |
2955 | } |
2956 | } |
2957 | } else if (IsOn(c.mVideo)) { |
2958 | videoType = MediaSourceEnum::Camera; |
2959 | Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE, |
2960 | (uint32_t)videoType); |
2961 | } |
2962 | |
2963 | if (c.mAudio.IsMediaTrackConstraints()) { |
2964 | auto& ac = c.mAudio.GetAsMediaTrackConstraints(); |
2965 | if (!ac.mMediaSource.WasPassed()) { |
2966 | ac.mMediaSource.Construct(NS_ConvertASCIItoUTF16( |
2967 | dom::GetEnumString(MediaSourceEnum::Microphone))); |
2968 | } |
2969 | audioType = dom::StringToEnum<MediaSourceEnum>(ac.mMediaSource.Value()) |
2970 | .valueOr(MediaSourceEnum::Other); |
2971 | Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE, |
2972 | (uint32_t)audioType); |
2973 | |
2974 | switch (audioType) { |
2975 | case MediaSourceEnum::Microphone: |
2976 | break; |
2977 | |
2978 | case MediaSourceEnum::AudioCapture: |
2979 | // Only enable AudioCapture if the pref is enabled. If it's not, we can |
2980 | // deny right away. |
2981 | if (!Preferences::GetBool("media.getusermedia.audio.capture.enabled")) { |
2982 | return StreamPromise::CreateAndReject( |
2983 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
2984 | __func__); |
2985 | } |
2986 | break; |
2987 | |
2988 | case MediaSourceEnum::Other: |
2989 | default: { |
2990 | return StreamPromise::CreateAndReject( |
2991 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::OverconstrainedError, |
2992 | "", u"mediaSource"_ns), |
2993 | __func__); |
2994 | } |
2995 | } |
2996 | } else if (IsOn(c.mAudio)) { |
2997 | audioType = MediaSourceEnum::Microphone; |
2998 | Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE, |
2999 | (uint32_t)audioType); |
3000 | } |
3001 | |
3002 | // Create a window listener if it doesn't already exist. |
3003 | RefPtr<GetUserMediaWindowListener> windowListener = |
3004 | GetOrMakeWindowListener(aWindow); |
3005 | MOZ_ASSERT(windowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener" ")"); do { *((volatile int*)__null) = 3005; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3006 | // Create an inactive DeviceListener to act as a placeholder, so the |
3007 | // window listener doesn't clean itself up until we're done. |
3008 | auto placeholderListener = MakeRefPtr<DeviceListener>(); |
3009 | windowListener->Register(placeholderListener); |
3010 | |
3011 | { // Check Permissions Policy. Reject if a requested feature is disabled. |
3012 | bool disabled = !IsOn(c.mAudio) && !IsOn(c.mVideo); |
3013 | if (IsOn(c.mAudio)) { |
3014 | if (audioType == MediaSourceEnum::Microphone) { |
3015 | if (Preferences::GetBool("media.getusermedia.microphone.deny", false) || |
3016 | !FeaturePolicyUtils::IsFeatureAllowed(doc, u"microphone"_ns)) { |
3017 | disabled = true; |
3018 | } |
3019 | } else if (!FeaturePolicyUtils::IsFeatureAllowed(doc, |
3020 | u"display-capture"_ns)) { |
3021 | disabled = true; |
3022 | } |
3023 | } |
3024 | if (IsOn(c.mVideo)) { |
3025 | if (videoType == MediaSourceEnum::Camera) { |
3026 | if (Preferences::GetBool("media.getusermedia.camera.deny", false) || |
3027 | !FeaturePolicyUtils::IsFeatureAllowed(doc, u"camera"_ns)) { |
3028 | disabled = true; |
3029 | } |
3030 | } else if (!FeaturePolicyUtils::IsFeatureAllowed(doc, |
3031 | u"display-capture"_ns)) { |
3032 | disabled = true; |
3033 | } |
3034 | } |
3035 | |
3036 | if (disabled) { |
3037 | placeholderListener->Stop(); |
3038 | return StreamPromise::CreateAndReject( |
3039 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
3040 | __func__); |
3041 | } |
3042 | } |
3043 | |
3044 | // Get list of all devices, with origin-specific device ids. |
3045 | |
3046 | MediaEnginePrefs prefs = mPrefs; |
3047 | |
3048 | nsString callID; |
3049 | rv = GenerateUUID(callID); |
3050 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3050); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3050; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3051 | |
3052 | bool hasVideo = videoType != MediaSourceEnum::Other; |
3053 | bool hasAudio = audioType != MediaSourceEnum::Other; |
3054 | |
3055 | // Handle fake requests from content. For gUM we don't consider resist |
3056 | // fingerprinting as users should be prompted anyway. |
3057 | bool forceFakes = c.mFake.WasPassed() && c.mFake.Value(); |
3058 | // fake:true is effective only for microphone and camera devices, so |
3059 | // permission must be requested for screen capture even if fake:true is set. |
3060 | bool hasOnlyForcedFakes = |
3061 | forceFakes && (!hasVideo || videoType == MediaSourceEnum::Camera) && |
3062 | (!hasAudio || audioType == MediaSourceEnum::Microphone); |
3063 | bool askPermission = |
3064 | (!privileged || |
3065 | Preferences::GetBool("media.navigator.permission.force")) && |
3066 | (!hasOnlyForcedFakes || |
3067 | Preferences::GetBool("media.navigator.permission.fake")); |
3068 | |
3069 | LOG("%s: Preparing to enumerate devices. windowId=%" PRIu64"l" "u" |
3070 | ", videoType=%" PRIu8"u" ", audioType=%" PRIu8"u" |
3071 | ", forceFakes=%s, askPermission=%s", |
3072 | __func__, windowID, static_cast<uint8_t>(videoType), |
3073 | static_cast<uint8_t>(audioType), forceFakes ? "true" : "false", |
3074 | askPermission ? "true" : "false"); |
3075 | |
3076 | EnumerationFlags flags = EnumerationFlag::AllowPermissionRequest; |
3077 | if (forceFakes) { |
3078 | flags += EnumerationFlag::ForceFakes; |
3079 | } |
3080 | RefPtr<MediaManager> self = this; |
3081 | return EnumerateDevicesImpl( |
3082 | aWindow, CreateEnumerationParams(videoType, audioType, flags)) |
3083 | ->Then( |
3084 | GetCurrentSerialEventTarget(), __func__, |
3085 | [self, windowID, c, windowListener, |
3086 | aCallerType](RefPtr<LocalMediaDeviceSetRefCnt> aDevices) { |
3087 | LOG("GetUserMedia: post enumeration promise success callback " |
3088 | "starting"); |
3089 | // Ensure that our windowID is still good. |
3090 | RefPtr<nsPIDOMWindowInner> window = |
3091 | nsGlobalWindowInner::GetInnerWindowWithId(windowID); |
3092 | if (!window || !self->IsWindowListenerStillActive(windowListener)) { |
3093 | LOG("GetUserMedia: bad window (%" PRIu64"l" "u" |
3094 | ") in post enumeration success callback!", |
3095 | windowID); |
3096 | return LocalDeviceSetPromise::CreateAndReject( |
3097 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3098 | __func__); |
3099 | } |
3100 | // Apply any constraints. This modifies the passed-in list. |
3101 | return self->SelectSettings(c, aCallerType, std::move(aDevices)); |
3102 | }, |
3103 | [](RefPtr<MediaMgrError>&& aError) { |
3104 | LOG("GetUserMedia: post enumeration EnumerateDevicesImpl " |
3105 | "failure callback called!"); |
3106 | return LocalDeviceSetPromise::CreateAndReject(std::move(aError), |
3107 | __func__); |
3108 | }) |
3109 | ->Then( |
3110 | GetCurrentSerialEventTarget(), __func__, |
3111 | [self, windowID, c, windowListener, placeholderListener, hasAudio, |
3112 | hasVideo, askPermission, prefs, isSecure, isHandlingUserInput, |
3113 | callID, principalInfo, aCallerType, resistFingerprinting]( |
3114 | RefPtr<LocalMediaDeviceSetRefCnt> aDevices) mutable { |
3115 | LOG("GetUserMedia: starting post enumeration promise2 success " |
3116 | "callback!"); |
3117 | |
3118 | // Ensure that the window is still good. |
3119 | RefPtr<nsPIDOMWindowInner> window = |
3120 | nsGlobalWindowInner::GetInnerWindowWithId(windowID); |
3121 | if (!window || !self->IsWindowListenerStillActive(windowListener)) { |
3122 | LOG("GetUserMedia: bad window (%" PRIu64"l" "u" |
3123 | ") in post enumeration success callback 2!", |
3124 | windowID); |
3125 | placeholderListener->Stop(); |
3126 | return StreamPromise::CreateAndReject( |
3127 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3128 | __func__); |
3129 | } |
3130 | if (!aDevices->Length()) { |
3131 | LOG("GetUserMedia: no devices found in post enumeration promise2 " |
3132 | "success callback! Calling error handler!"); |
3133 | placeholderListener->Stop(); |
3134 | // When privacy.resistFingerprinting = true, no |
3135 | // available device implies content script is requesting |
3136 | // a fake device, so report NotAllowedError. |
3137 | auto error = resistFingerprinting |
3138 | ? MediaMgrError::Name::NotAllowedError |
3139 | : MediaMgrError::Name::NotFoundError; |
3140 | return StreamPromise::CreateAndReject( |
3141 | MakeRefPtr<MediaMgrError>(error), __func__); |
3142 | } |
3143 | |
3144 | // Time to start devices. Create the necessary device listeners and |
3145 | // remove the placeholder. |
3146 | RefPtr<DeviceListener> audioListener; |
3147 | RefPtr<DeviceListener> videoListener; |
3148 | if (hasAudio) { |
3149 | audioListener = MakeRefPtr<DeviceListener>(); |
3150 | windowListener->Register(audioListener); |
3151 | } |
3152 | if (hasVideo) { |
3153 | videoListener = MakeRefPtr<DeviceListener>(); |
3154 | windowListener->Register(videoListener); |
3155 | } |
3156 | placeholderListener->Stop(); |
3157 | |
3158 | bool focusSource = mozilla::Preferences::GetBool( |
3159 | "media.getusermedia.window.focus_source.enabled", true); |
3160 | |
3161 | // Incremental hack to compile. To be replaced by deeper |
3162 | // refactoring. MediaManager allows |
3163 | // "neither-resolve-nor-reject" semantics, so we cannot |
3164 | // use MozPromiseHolder here. |
3165 | MozPromiseHolder<StreamPromise> holder; |
3166 | RefPtr<StreamPromise> p = holder.Ensure(__func__); |
3167 | |
3168 | // Pass callbacks and listeners along to GetUserMediaStreamTask. |
3169 | auto task = MakeRefPtr<GetUserMediaStreamTask>( |
3170 | c, std::move(holder), windowID, std::move(windowListener), |
3171 | std::move(audioListener), std::move(videoListener), prefs, |
3172 | principalInfo, aCallerType, focusSource); |
3173 | |
3174 | // It is time to ask for user permission, prime voice processing |
3175 | // now. Use a local lambda to enable a guard pattern. |
3176 | [&] { |
3177 | if (!StaticPrefs:: |
3178 | media_getusermedia_microphone_voice_stream_priming_enabled() || |
3179 | !StaticPrefs:: |
3180 | media_getusermedia_microphone_prefer_voice_stream_with_processing_enabled()) { |
3181 | return; |
3182 | } |
3183 | |
3184 | if (const auto fc = FlattenedConstraints( |
3185 | NormalizedConstraints(GetInvariant(c.mAudio))); |
3186 | !fc.mEchoCancellation.Get(prefs.mAecOn) && |
3187 | !fc.mAutoGainControl.Get(prefs.mAgcOn && prefs.mAecOn) && |
3188 | !fc.mNoiseSuppression.Get(prefs.mNoiseOn && prefs.mAecOn)) { |
3189 | return; |
3190 | } |
3191 | |
3192 | if (GetPersistentPermissions(windowID) |
3193 | .map([](auto&& aState) { |
3194 | return aState.mMicrophonePermission == |
3195 | PersistentPermissionState::Deny; |
3196 | }) |
3197 | .unwrapOr(true)) { |
3198 | return; |
3199 | } |
3200 | |
3201 | task->PrimeVoiceProcessing(); |
3202 | }(); |
3203 | |
3204 | size_t taskCount = |
3205 | self->AddTaskAndGetCount(windowID, callID, std::move(task)); |
3206 | |
3207 | if (!askPermission) { |
3208 | self->NotifyAllowed(callID, *aDevices); |
3209 | } else { |
3210 | auto req = MakeRefPtr<GetUserMediaRequest>( |
3211 | window, callID, std::move(aDevices), c, isSecure, |
3212 | isHandlingUserInput); |
3213 | if (!Preferences::GetBool("media.navigator.permission.force") && |
3214 | taskCount > 1) { |
3215 | // there is at least 1 pending gUM request |
3216 | // For the scarySources test case, always send the |
3217 | // request |
3218 | self->mPendingGUMRequest.AppendElement(req.forget()); |
3219 | } else { |
3220 | nsCOMPtr<nsIObserverService> obs = |
3221 | services::GetObserverService(); |
3222 | obs->NotifyObservers(req, "getUserMedia:request", nullptr); |
3223 | } |
3224 | } |
3225 | #ifdef MOZ_WEBRTC1 |
3226 | self->mLogHandle = EnsureWebrtcLogging(); |
3227 | #endif |
3228 | return p; |
3229 | }, |
3230 | [placeholderListener](RefPtr<MediaMgrError>&& aError) { |
3231 | LOG("GetUserMedia: post enumeration SelectSettings failure " |
3232 | "callback called!"); |
3233 | placeholderListener->Stop(); |
3234 | return StreamPromise::CreateAndReject(std::move(aError), __func__); |
3235 | }); |
3236 | }; |
3237 | |
3238 | RefPtr<LocalDeviceSetPromise> MediaManager::AnonymizeDevices( |
3239 | nsPIDOMWindowInner* aWindow, RefPtr<const MediaDeviceSetRefCnt> aDevices) { |
3240 | // Get an origin-key (for either regular or private browsing). |
3241 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3241; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3242 | uint64_t windowId = aWindow->WindowID(); |
3243 | nsCOMPtr<nsIPrincipal> principal = |
3244 | nsGlobalWindowInner::Cast(aWindow)->GetPrincipal(); |
3245 | MOZ_ASSERT(principal)do { static_assert( mozilla::detail::AssertionConditionType< decltype(principal)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(principal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal" ")" ); do { *((volatile int*)__null) = 3245; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3246 | ipc::PrincipalInfo principalInfo; |
3247 | nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo); |
3248 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3248)) { |
3249 | return LocalDeviceSetPromise::CreateAndReject( |
3250 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
3251 | __func__); |
3252 | } |
3253 | bool persist = IsActivelyCapturingOrHasAPermission(windowId); |
3254 | return media::GetPrincipalKey(principalInfo, persist) |
3255 | ->Then( |
3256 | GetMainThreadSerialEventTarget(), __func__, |
3257 | [rawDevices = std::move(aDevices), |
3258 | windowId](const nsCString& aOriginKey) { |
3259 | MOZ_ASSERT(!aOriginKey.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!aOriginKey.IsEmpty())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!aOriginKey.IsEmpty()))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!aOriginKey.IsEmpty()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3259); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOriginKey.IsEmpty()" ")"); do { *((volatile int*)__null) = 3259; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3260 | RefPtr anonymized = new LocalMediaDeviceSetRefCnt(); |
3261 | for (const RefPtr<MediaDevice>& device : *rawDevices) { |
3262 | nsString id = device->mRawID; |
3263 | // An empty id represents a virtual default device, for which |
3264 | // the exposed deviceId is the empty string. |
3265 | if (!id.IsEmpty()) { |
3266 | nsContentUtils::AnonymizeId(id, aOriginKey); |
3267 | } |
3268 | nsString groupId = device->mRawGroupID; |
3269 | // Use window id to salt group id in order to make it session |
3270 | // based as required by the spec. This does not provide unique |
3271 | // group ids through out a browser restart. However, this is not |
3272 | // against the spec. Furthermore, since device ids are the same |
3273 | // after a browser restart the fingerprint is not bigger. |
3274 | groupId.AppendInt(windowId); |
3275 | nsContentUtils::AnonymizeId(groupId, aOriginKey); |
3276 | |
3277 | nsString name = device->mRawName; |
3278 | if (name.Find(u"AirPods"_ns) != -1) { |
3279 | name = u"AirPods"_ns; |
3280 | } |
3281 | anonymized->EmplaceBack( |
3282 | new LocalMediaDevice(device, id, groupId, name)); |
3283 | } |
3284 | return LocalDeviceSetPromise::CreateAndResolve(anonymized, |
3285 | __func__); |
3286 | }, |
3287 | [](nsresult rs) { |
3288 | NS_WARNING("AnonymizeDevices failed to get Principal Key")NS_DebugBreak(NS_DEBUG_WARNING, "AnonymizeDevices failed to get Principal Key" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3288); |
3289 | return LocalDeviceSetPromise::CreateAndReject( |
3290 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3291 | __func__); |
3292 | }); |
3293 | } |
3294 | |
3295 | RefPtr<LocalDeviceSetPromise> MediaManager::EnumerateDevicesImpl( |
3296 | nsPIDOMWindowInner* aWindow, EnumerationParams aParams) { |
3297 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3297; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3298 | |
3299 | uint64_t windowId = aWindow->WindowID(); |
3300 | LOG("%s: windowId=%" PRIu64"l" "u" ", aVideoInputType=%" PRIu8"u" |
3301 | ", aAudioInputType=%" PRIu8"u", |
3302 | __func__, windowId, static_cast<uint8_t>(aParams.VideoInputType()), |
3303 | static_cast<uint8_t>(aParams.AudioInputType())); |
3304 | |
3305 | // To get a device list anonymized for a particular origin, we must: |
3306 | // 1. Get the raw devices list |
3307 | // 2. Anonymize the raw list with an origin-key. |
3308 | |
3309 | // Add the window id here to check for that and abort silently if no longer |
3310 | // exists. |
3311 | RefPtr<GetUserMediaWindowListener> windowListener = |
3312 | GetOrMakeWindowListener(aWindow); |
3313 | MOZ_ASSERT(windowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(windowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(windowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("windowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "windowListener" ")"); do { *((volatile int*)__null) = 3313; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3314 | // Create an inactive DeviceListener to act as a placeholder, so the |
3315 | // window listener doesn't clean itself up until we're done. |
3316 | auto placeholderListener = MakeRefPtr<DeviceListener>(); |
3317 | windowListener->Register(placeholderListener); |
3318 | |
3319 | return MaybeRequestPermissionAndEnumerateRawDevices(std::move(aParams)) |
3320 | ->Then( |
3321 | GetMainThreadSerialEventTarget(), __func__, |
3322 | [self = RefPtr(this), this, window = nsCOMPtr(aWindow), |
3323 | placeholderListener](RefPtr<MediaDeviceSetRefCnt> aDevices) mutable { |
3324 | // Only run if window is still on our active list. |
3325 | MediaManager* mgr = MediaManager::GetIfExists(); |
3326 | if (!mgr || placeholderListener->Stopped()) { |
3327 | // The listener has already been removed if the window is no |
3328 | // longer active. |
3329 | return LocalDeviceSetPromise::CreateAndReject( |
3330 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3331 | __func__); |
3332 | } |
3333 | MOZ_ASSERT(mgr->IsWindowStillActive(window->WindowID()))do { static_assert( mozilla::detail::AssertionConditionType< decltype(mgr->IsWindowStillActive(window->WindowID()))> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(mgr->IsWindowStillActive(window->WindowID()))) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mgr->IsWindowStillActive(window->WindowID())" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3333); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mgr->IsWindowStillActive(window->WindowID())" ")"); do { *((volatile int*)__null) = 3333; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3334 | placeholderListener->Stop(); |
3335 | return AnonymizeDevices(window, aDevices); |
3336 | }, |
3337 | [placeholderListener](RefPtr<MediaMgrError>&& aError) { |
3338 | // EnumerateDevicesImpl may fail if a new doc has been set, in which |
3339 | // case the OnNavigation() method should have removed all previous |
3340 | // active listeners, or if a platform device access request was not |
3341 | // granted. |
3342 | placeholderListener->Stop(); |
3343 | return LocalDeviceSetPromise::CreateAndReject(std::move(aError), |
3344 | __func__); |
3345 | }); |
3346 | } |
3347 | |
3348 | RefPtr<LocalDevicePromise> MediaManager::SelectAudioOutput( |
3349 | nsPIDOMWindowInner* aWindow, const dom::AudioOutputOptions& aOptions, |
3350 | CallerType aCallerType) { |
3351 | bool isHandlingUserInput = UserActivation::IsHandlingUserInput(); |
3352 | nsCOMPtr<nsIPrincipal> principal = |
3353 | nsGlobalWindowInner::Cast(aWindow)->GetPrincipal(); |
3354 | if (!FeaturePolicyUtils::IsFeatureAllowed(aWindow->GetExtantDoc(), |
3355 | u"speaker-selection"_ns)) { |
3356 | return LocalDevicePromise::CreateAndReject( |
3357 | MakeRefPtr<MediaMgrError>( |
3358 | MediaMgrError::Name::NotAllowedError, |
3359 | "Document's Permissions Policy does not allow selectAudioOutput()"), |
3360 | __func__); |
3361 | } |
3362 | if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3362)) { |
3363 | return LocalDevicePromise::CreateAndReject( |
3364 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
3365 | __func__); |
3366 | } |
3367 | // Disallow access to null principal. |
3368 | if (principal->GetIsNullPrincipal()) { |
3369 | return LocalDevicePromise::CreateAndReject( |
3370 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError), |
3371 | __func__); |
3372 | } |
3373 | ipc::PrincipalInfo principalInfo; |
3374 | nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo); |
3375 | if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv )), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3375)) { |
3376 | return LocalDevicePromise::CreateAndReject( |
3377 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError), |
3378 | __func__); |
3379 | } |
3380 | uint64_t windowID = aWindow->WindowID(); |
3381 | const bool resistFingerprinting = |
3382 | aWindow->AsGlobal()->ShouldResistFingerprinting(aCallerType, |
3383 | RFPTarget::MediaDevices); |
3384 | return EnumerateDevicesImpl( |
3385 | aWindow, CreateEnumerationParams( |
3386 | MediaSourceEnum::Other, MediaSourceEnum::Other, |
3387 | {EnumerationFlag::EnumerateAudioOutputs, |
3388 | EnumerationFlag::AllowPermissionRequest})) |
3389 | ->Then( |
3390 | GetCurrentSerialEventTarget(), __func__, |
3391 | [self = RefPtr<MediaManager>(this), windowID, aOptions, aCallerType, |
3392 | resistFingerprinting, isHandlingUserInput, |
3393 | principalInfo](RefPtr<LocalMediaDeviceSetRefCnt> aDevices) mutable { |
3394 | // Ensure that the window is still good. |
3395 | RefPtr<nsPIDOMWindowInner> window = |
3396 | nsGlobalWindowInner::GetInnerWindowWithId(windowID); |
3397 | if (!window) { |
3398 | LOG("SelectAudioOutput: bad window (%" PRIu64"l" "u" |
3399 | ") in post enumeration success callback!", |
3400 | windowID); |
3401 | return LocalDevicePromise::CreateAndReject( |
3402 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), |
3403 | __func__); |
3404 | } |
3405 | if (aDevices->IsEmpty()) { |
3406 | LOG("SelectAudioOutput: no devices found"); |
3407 | auto error = resistFingerprinting |
3408 | ? MediaMgrError::Name::NotAllowedError |
3409 | : MediaMgrError::Name::NotFoundError; |
3410 | return LocalDevicePromise::CreateAndReject( |
3411 | MakeRefPtr<MediaMgrError>(error), __func__); |
3412 | } |
3413 | MozPromiseHolder<LocalDevicePromise> holder; |
3414 | RefPtr<LocalDevicePromise> p = holder.Ensure(__func__); |
3415 | auto task = MakeRefPtr<SelectAudioOutputTask>( |
3416 | std::move(holder), windowID, aCallerType, principalInfo); |
3417 | nsString callID; |
3418 | nsresult rv = GenerateUUID(callID); |
3419 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3419); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3419; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3420 | size_t taskCount = |
3421 | self->AddTaskAndGetCount(windowID, callID, std::move(task)); |
3422 | bool askPermission = |
3423 | !Preferences::GetBool("media.navigator.permission.disabled") || |
3424 | Preferences::GetBool("media.navigator.permission.force"); |
3425 | if (!askPermission) { |
3426 | self->NotifyAllowed(callID, *aDevices); |
3427 | } else { |
3428 | MOZ_ASSERT(window->IsSecureContext())do { static_assert( mozilla::detail::AssertionConditionType< decltype(window->IsSecureContext())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(window->IsSecureContext() ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "window->IsSecureContext()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "window->IsSecureContext()" ")"); do { *((volatile int*)__null) = 3428; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3429 | auto req = MakeRefPtr<GetUserMediaRequest>( |
3430 | window, callID, std::move(aDevices), aOptions, true, |
3431 | isHandlingUserInput); |
3432 | if (taskCount > 1) { |
3433 | // there is at least 1 pending gUM request |
3434 | self->mPendingGUMRequest.AppendElement(req.forget()); |
3435 | } else { |
3436 | nsCOMPtr<nsIObserverService> obs = |
3437 | services::GetObserverService(); |
3438 | obs->NotifyObservers(req, "getUserMedia:request", nullptr); |
3439 | } |
3440 | } |
3441 | return p; |
3442 | }, |
3443 | [](RefPtr<MediaMgrError> aError) { |
3444 | LOG("SelectAudioOutput: EnumerateDevicesImpl " |
3445 | "failure callback called!"); |
3446 | return LocalDevicePromise::CreateAndReject(std::move(aError), |
3447 | __func__); |
3448 | }); |
3449 | } |
3450 | |
3451 | MediaEngine* MediaManager::GetBackend() { |
3452 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3452; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3453 | // Plugin backends as appropriate. The default engine also currently |
3454 | // includes picture support for Android. |
3455 | // This IS called off main-thread. |
3456 | if (!mBackend) { |
3457 | #if defined(MOZ_WEBRTC1) |
3458 | mBackend = new MediaEngineWebRTC(); |
3459 | #else |
3460 | mBackend = new MediaEngineFake(); |
3461 | #endif |
3462 | mDeviceListChangeListener = mBackend->DeviceListChangeEvent().Connect( |
3463 | AbstractThread::MainThread(), this, &MediaManager::DeviceListChanged); |
3464 | } |
3465 | return mBackend; |
3466 | } |
3467 | |
3468 | void MediaManager::OnNavigation(uint64_t aWindowID) { |
3469 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3469); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3469; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3470 | LOG("OnNavigation for %" PRIu64"l" "u", aWindowID); |
3471 | |
3472 | // Stop the streams for this window. The runnables check this value before |
3473 | // making a call to content. |
3474 | |
3475 | nsTArray<nsString>* callIDs; |
3476 | if (mCallIds.Get(aWindowID, &callIDs)) { |
3477 | for (auto& callID : *callIDs) { |
3478 | mActiveCallbacks.Remove(callID); |
3479 | for (auto& request : mPendingGUMRequest.Clone()) { |
3480 | nsString id; |
3481 | request->GetCallID(id); |
3482 | if (id == callID) { |
3483 | mPendingGUMRequest.RemoveElement(request); |
3484 | } |
3485 | } |
3486 | } |
3487 | mCallIds.Remove(aWindowID); |
3488 | } |
3489 | |
3490 | if (RefPtr<GetUserMediaWindowListener> listener = |
3491 | GetWindowListener(aWindowID)) { |
3492 | listener->RemoveAll(); |
3493 | } |
3494 | MOZ_ASSERT(!GetWindowListener(aWindowID))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!GetWindowListener(aWindowID))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!GetWindowListener(aWindowID )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!GetWindowListener(aWindowID)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!GetWindowListener(aWindowID)" ")"); do { *((volatile int*)__null) = 3494; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3495 | } |
3496 | |
3497 | void MediaManager::OnCameraMute(bool aMute) { |
3498 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3498; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3499 | LOG("OnCameraMute for all windows"); |
3500 | mCamerasMuted = aMute; |
3501 | // This is safe since we're on main-thread, and the windowlist can only |
3502 | // be added to from the main-thread |
3503 | for (const auto& window : mActiveWindows.Values()) { |
3504 | window->MuteOrUnmuteCameras(aMute); |
3505 | } |
3506 | } |
3507 | |
3508 | void MediaManager::OnMicrophoneMute(bool aMute) { |
3509 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3509); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3509; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3510 | LOG("OnMicrophoneMute for all windows"); |
3511 | mMicrophonesMuted = aMute; |
3512 | // This is safe since we're on main-thread, and the windowlist can only |
3513 | // be added to from the main-thread |
3514 | for (const auto& window : mActiveWindows.Values()) { |
3515 | window->MuteOrUnmuteMicrophones(aMute); |
3516 | } |
3517 | } |
3518 | |
3519 | RefPtr<GetUserMediaWindowListener> MediaManager::GetOrMakeWindowListener( |
3520 | nsPIDOMWindowInner* aWindow) { |
3521 | Document* doc = aWindow->GetExtantDoc(); |
3522 | if (!doc) { |
3523 | // The window has been destroyed. Destroyed windows don't have listeners. |
3524 | return nullptr; |
3525 | } |
3526 | nsIPrincipal* principal = doc->NodePrincipal(); |
3527 | uint64_t windowId = aWindow->WindowID(); |
3528 | RefPtr<GetUserMediaWindowListener> windowListener = |
3529 | GetWindowListener(windowId); |
3530 | if (windowListener) { |
3531 | MOZ_ASSERT(PrincipalHandleMatches(windowListener->GetPrincipalHandle(),do { static_assert( mozilla::detail::AssertionConditionType< decltype(PrincipalHandleMatches(windowListener->GetPrincipalHandle (), principal))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(PrincipalHandleMatches(windowListener ->GetPrincipalHandle(), principal)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)" ")"); do { *((volatile int*)__null) = 3532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
3532 | principal))do { static_assert( mozilla::detail::AssertionConditionType< decltype(PrincipalHandleMatches(windowListener->GetPrincipalHandle (), principal))>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(PrincipalHandleMatches(windowListener ->GetPrincipalHandle(), principal)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "PrincipalHandleMatches(windowListener->GetPrincipalHandle(), principal)" ")"); do { *((volatile int*)__null) = 3532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3533 | } else { |
3534 | windowListener = new GetUserMediaWindowListener( |
3535 | windowId, MakePrincipalHandle(principal)); |
3536 | AddWindowID(windowId, windowListener); |
3537 | } |
3538 | return windowListener; |
3539 | } |
3540 | |
3541 | void MediaManager::AddWindowID(uint64_t aWindowId, |
3542 | RefPtr<GetUserMediaWindowListener> aListener) { |
3543 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3543; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3544 | // Store the WindowID in a hash table and mark as active. The entry is removed |
3545 | // when this window is closed or navigated away from. |
3546 | // This is safe since we're on main-thread, and the windowlist can only |
3547 | // be invalidated from the main-thread (see OnNavigation) |
3548 | if (IsWindowStillActive(aWindowId)) { |
3549 | MOZ_ASSERT(false, "Window already added")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "Window already added" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3549); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Window already added" ")"); do { *((volatile int*)__null) = 3549; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
3550 | return; |
3551 | } |
3552 | |
3553 | aListener->MuteOrUnmuteCameras(mCamerasMuted); |
3554 | aListener->MuteOrUnmuteMicrophones(mMicrophonesMuted); |
3555 | GetActiveWindows()->InsertOrUpdate(aWindowId, std::move(aListener)); |
3556 | |
3557 | RefPtr<WindowGlobalChild> wgc = |
3558 | WindowGlobalChild::GetByInnerWindowId(aWindowId); |
3559 | if (wgc) { |
3560 | wgc->BlockBFCacheFor(BFCacheStatus::ACTIVE_GET_USER_MEDIA); |
3561 | } |
3562 | } |
3563 | |
3564 | void MediaManager::RemoveWindowID(uint64_t aWindowId) { |
3565 | RefPtr<WindowGlobalChild> wgc = |
3566 | WindowGlobalChild::GetByInnerWindowId(aWindowId); |
3567 | if (wgc) { |
3568 | wgc->UnblockBFCacheFor(BFCacheStatus::ACTIVE_GET_USER_MEDIA); |
3569 | } |
3570 | |
3571 | mActiveWindows.Remove(aWindowId); |
3572 | |
3573 | // get outer windowID |
3574 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowId); |
3575 | if (!window) { |
3576 | LOG("No inner window for %" PRIu64"l" "u", aWindowId); |
3577 | return; |
3578 | } |
3579 | |
3580 | auto* outer = window->GetOuterWindow(); |
3581 | if (!outer) { |
3582 | LOG("No outer window for inner %" PRIu64"l" "u", aWindowId); |
3583 | return; |
3584 | } |
3585 | |
3586 | uint64_t outerID = outer->WindowID(); |
3587 | |
3588 | // Notify the UI that this window no longer has gUM active |
3589 | char windowBuffer[32]; |
3590 | SprintfLiteral(windowBuffer, "%" PRIu64"l" "u", outerID); |
3591 | nsString data = NS_ConvertUTF8toUTF16(windowBuffer); |
3592 | |
3593 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
3594 | obs->NotifyWhenScriptSafe(nullptr, "recording-window-ended", data.get()); |
3595 | LOG("Sent recording-window-ended for window %" PRIu64"l" "u" " (outer %" PRIu64"l" "u" ")", |
3596 | aWindowId, outerID); |
3597 | } |
3598 | |
3599 | bool MediaManager::IsWindowListenerStillActive( |
3600 | const RefPtr<GetUserMediaWindowListener>& aListener) { |
3601 | MOZ_DIAGNOSTIC_ASSERT(aListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aListener", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3601); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aListener" ")"); do { *((volatile int*)__null) = 3601; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3602 | return aListener && aListener == GetWindowListener(aListener->WindowID()); |
3603 | } |
3604 | |
3605 | void MediaManager::GetPref(nsIPrefBranch* aBranch, const char* aPref, |
3606 | const char* aData, int32_t* aVal) { |
3607 | int32_t temp; |
3608 | if (aData == nullptr || strcmp(aPref, aData) == 0) { |
3609 | if (NS_SUCCEEDED(aBranch->GetIntPref(aPref, &temp))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aBranch->GetIntPref (aPref, &temp))), 1)))) { |
3610 | *aVal = temp; |
3611 | } |
3612 | } |
3613 | } |
3614 | |
3615 | void MediaManager::GetPrefBool(nsIPrefBranch* aBranch, const char* aPref, |
3616 | const char* aData, bool* aVal) { |
3617 | bool temp; |
3618 | if (aData == nullptr || strcmp(aPref, aData) == 0) { |
3619 | if (NS_SUCCEEDED(aBranch->GetBoolPref(aPref, &temp))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aBranch->GetBoolPref (aPref, &temp))), 1)))) { |
3620 | *aVal = temp; |
3621 | } |
3622 | } |
3623 | } |
3624 | |
3625 | void MediaManager::GetPrefs(nsIPrefBranch* aBranch, const char* aData) { |
3626 | GetPref(aBranch, "media.navigator.video.default_width", aData, |
3627 | &mPrefs.mWidth); |
3628 | GetPref(aBranch, "media.navigator.video.default_height", aData, |
3629 | &mPrefs.mHeight); |
3630 | GetPref(aBranch, "media.navigator.video.default_fps", aData, &mPrefs.mFPS); |
3631 | GetPref(aBranch, "media.navigator.audio.fake_frequency", aData, |
3632 | &mPrefs.mFreq); |
3633 | #ifdef MOZ_WEBRTC1 |
3634 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.platform.enabled", |
3635 | aData, &mPrefs.mUsePlatformProcessing); |
3636 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.aec.enabled", aData, |
3637 | &mPrefs.mAecOn); |
3638 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.agc.enabled", aData, |
3639 | &mPrefs.mAgcOn); |
3640 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.hpf.enabled", aData, |
3641 | &mPrefs.mHPFOn); |
3642 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.noise.enabled", |
3643 | aData, &mPrefs.mNoiseOn); |
3644 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.transient.enabled", |
3645 | aData, &mPrefs.mTransientOn); |
3646 | GetPrefBool(aBranch, "media.getusermedia.audio.processing.agc2.forced", aData, |
3647 | &mPrefs.mAgc2Forced); |
3648 | // Use 0 or 1 to force to false or true |
3649 | // EchoCanceller3Config::echo_removal_control.has_clock_drift. |
3650 | // -1 is the default, which means automatically set has_clock_drift as |
3651 | // deemed appropriate. |
3652 | GetPref(aBranch, "media.getusermedia.audio.processing.aec.expect_drift", |
3653 | aData, &mPrefs.mExpectDrift); |
3654 | GetPref(aBranch, "media.getusermedia.audio.processing.agc", aData, |
3655 | &mPrefs.mAgc); |
3656 | GetPref(aBranch, "media.getusermedia.audio.processing.noise", aData, |
3657 | &mPrefs.mNoise); |
3658 | GetPref(aBranch, "media.getusermedia.audio.max_channels", aData, |
3659 | &mPrefs.mChannels); |
3660 | #endif |
3661 | LOG("%s: default prefs: %dx%d @%dfps, %dHz test tones, platform processing: " |
3662 | "%s, aec: %s, agc: %s, hpf: %s, noise: %s, drift: %s, agc level: %d, agc " |
3663 | "version: " |
3664 | "%s, noise level: %d, transient: %s, channels %d", |
3665 | __FUNCTION__, mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mFreq, |
3666 | mPrefs.mUsePlatformProcessing ? "on" : "off", |
3667 | mPrefs.mAecOn ? "on" : "off", mPrefs.mAgcOn ? "on" : "off", |
3668 | mPrefs.mHPFOn ? "on" : "off", mPrefs.mNoiseOn ? "on" : "off", |
3669 | mPrefs.mExpectDrift < 0 ? "auto" |
3670 | : mPrefs.mExpectDrift ? "on" |
3671 | : "off", |
3672 | mPrefs.mAgc, mPrefs.mAgc2Forced ? "2" : "1", mPrefs.mNoise, |
3673 | mPrefs.mTransientOn ? "on" : "off", mPrefs.mChannels); |
3674 | } |
3675 | |
3676 | void MediaManager::Shutdown() { |
3677 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3677); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3677; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3678 | if (sHasMainThreadShutdown) { |
3679 | return; |
3680 | } |
3681 | |
3682 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
3683 | |
3684 | obs->RemoveObserver(this, "last-pb-context-exited"); |
3685 | obs->RemoveObserver(this, "getUserMedia:privileged:allow"); |
3686 | obs->RemoveObserver(this, "getUserMedia:response:allow"); |
3687 | obs->RemoveObserver(this, "getUserMedia:response:deny"); |
3688 | obs->RemoveObserver(this, "getUserMedia:response:noOSPermission"); |
3689 | obs->RemoveObserver(this, "getUserMedia:revoke"); |
3690 | obs->RemoveObserver(this, "getUserMedia:muteVideo"); |
3691 | obs->RemoveObserver(this, "getUserMedia:unmuteVideo"); |
3692 | obs->RemoveObserver(this, "getUserMedia:muteAudio"); |
3693 | obs->RemoveObserver(this, "getUserMedia:unmuteAudio"); |
3694 | obs->RemoveObserver(this, "application-background"); |
3695 | obs->RemoveObserver(this, "application-foreground"); |
3696 | |
3697 | nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1"); |
3698 | if (prefs) { |
3699 | ForeachObservedPref([&](const nsLiteralCString& aPrefName) { |
3700 | prefs->RemoveObserver(aPrefName, this); |
3701 | }); |
3702 | } |
3703 | |
3704 | if (mDeviceChangeTimer) { |
3705 | mDeviceChangeTimer->Cancel(); |
3706 | // Drop ref to MediaTimer early to avoid blocking SharedThreadPool shutdown |
3707 | mDeviceChangeTimer = nullptr; |
3708 | } |
3709 | |
3710 | { |
3711 | // Close off any remaining active windows. |
3712 | |
3713 | // Live capture at this point is rare but can happen. Stopping it will make |
3714 | // the window listeners attempt to remove themselves from the active windows |
3715 | // table. We cannot touch the table at point so we grab a copy of the window |
3716 | // listeners first. |
3717 | const auto listeners = ToArray(GetActiveWindows()->Values()); |
3718 | for (const auto& listener : listeners) { |
3719 | listener->RemoveAll(); |
3720 | } |
3721 | } |
3722 | MOZ_ASSERT(GetActiveWindows()->Count() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(GetActiveWindows()->Count() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(GetActiveWindows()->Count () == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("GetActiveWindows()->Count() == 0", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3722); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetActiveWindows()->Count() == 0" ")"); do { *((volatile int*)__null) = 3722; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3723 | |
3724 | GetActiveWindows()->Clear(); |
3725 | mActiveCallbacks.Clear(); |
3726 | mCallIds.Clear(); |
3727 | mPendingGUMRequest.Clear(); |
3728 | #ifdef MOZ_WEBRTC1 |
3729 | mLogHandle = nullptr; |
3730 | #endif |
3731 | |
3732 | // From main thread's point of view, shutdown is now done. |
3733 | // All that remains is shutting down the media thread. |
3734 | sHasMainThreadShutdown = true; |
3735 | |
3736 | // Release the backend (and call Shutdown()) from within mMediaThread. |
3737 | // Don't use MediaManager::Dispatch() because we're |
3738 | // sHasMainThreadShutdown == true here! |
3739 | MOZ_ALWAYS_SUCCEEDS(mMediaThread->Dispatch(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3740 | NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3741 | LOG("MediaManager Thread Shutdown");do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3742 | MOZ_ASSERT(IsInMediaThread());do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3743 | // Must shutdown backend on MediaManager thread, since that'sdo { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3744 | // where we started it from!do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3745 | if (mBackend) {do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3746 | mBackend->Shutdown(); // idempotentdo { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3747 | mDeviceListChangeListener.DisconnectIfExists();do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3748 | }do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3749 | // last reference, will invoke Shutdown() againdo { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3750 | mBackend = nullptr;do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
3751 | })))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl (mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [ self = RefPtr(this), this]() { LOG("MediaManager Thread Shutdown" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInMediaThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInMediaThread()" ")"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); if (mBackend ) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists (); } mBackend = nullptr; })))), 1)))), 1))) { } else { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(false)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("false" " (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3751); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "NS_SUCCEEDED(mMediaThread->Dispatch( NS_NewRunnableFunction(__func__, [self = RefPtr(this), this]() { LOG(\"MediaManager Thread Shutdown\"); do { static_assert( mozilla::detail::AssertionConditionType<decltype(IsInMediaThread())>::isValid, \"invalid assertion condition\"); if ((__builtin_expect(!!(!(!!(IsInMediaThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(\"IsInMediaThread()\", \"/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp\", 3742); AnnotateMozCrashReason(\"MOZ_ASSERT\" \"(\" \"IsInMediaThread()\" \")\"); do { *((volatile int*)__null) = 3742; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (mBackend) { mBackend->Shutdown(); mDeviceListChangeListener.DisconnectIfExists(); } mBackend = nullptr; })))" ")"); do { *((volatile int*)__null) = 3751; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
3752 | |
3753 | // note that this == sSingleton |
3754 | MOZ_ASSERT(this == sSingleton)do { static_assert( mozilla::detail::AssertionConditionType< decltype(this == sSingleton)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(this == sSingleton))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("this == sSingleton" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3754); AnnotateMozCrashReason("MOZ_ASSERT" "(" "this == sSingleton" ")"); do { *((volatile int*)__null) = 3754; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3755 | |
3756 | // Explicitly shut down the TaskQueue so that it releases its |
3757 | // SharedThreadPool when all tasks have completed. SharedThreadPool blocks |
3758 | // XPCOM shutdown from proceeding beyond "xpcom-shutdown-threads" until all |
3759 | // SharedThreadPools are released, but the nsComponentManager keeps a |
3760 | // reference to the MediaManager for the nsIMediaManagerService until much |
3761 | // later in shutdown. This also provides additional assurance that no |
3762 | // further tasks will be queued. |
3763 | mMediaThread->BeginShutdown()->Then( |
3764 | GetMainThreadSerialEventTarget(), __func__, [] { |
3765 | LOG("MediaManager shutdown lambda running, releasing MediaManager " |
3766 | "singleton"); |
3767 | // Remove async shutdown blocker |
3768 | media::MustGetShutdownBarrier()->RemoveBlocker( |
3769 | sSingleton->mShutdownBlocker); |
3770 | |
3771 | sSingleton = nullptr; |
3772 | }); |
3773 | } |
3774 | |
3775 | void MediaManager::SendPendingGUMRequest() { |
3776 | if (mPendingGUMRequest.Length() > 0) { |
3777 | nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
3778 | obs->NotifyObservers(mPendingGUMRequest[0], "getUserMedia:request", |
3779 | nullptr); |
3780 | mPendingGUMRequest.RemoveElementAt(0); |
3781 | } |
3782 | } |
3783 | |
3784 | bool IsGUMResponseNoAccess(const char* aTopic, |
3785 | MediaMgrError::Name& aErrorName) { |
3786 | if (!strcmp(aTopic, "getUserMedia:response:deny")) { |
3787 | aErrorName = MediaMgrError::Name::NotAllowedError; |
3788 | return true; |
3789 | } |
3790 | |
3791 | if (!strcmp(aTopic, "getUserMedia:response:noOSPermission")) { |
3792 | aErrorName = MediaMgrError::Name::NotFoundError; |
3793 | return true; |
3794 | } |
3795 | |
3796 | return false; |
3797 | } |
3798 | |
3799 | static MediaSourceEnum ParseScreenColonWindowID(const char16_t* aData, |
3800 | uint64_t* aWindowIDOut) { |
3801 | MOZ_ASSERT(aWindowIDOut)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aWindowIDOut)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aWindowIDOut))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aWindowIDOut", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowIDOut" ")"); do { *((volatile int*)__null) = 3801; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3802 | // may be windowid or screen:windowid |
3803 | const nsDependentString data(aData); |
3804 | if (Substring(data, 0, strlen("screen:")).EqualsLiteral("screen:")) { |
3805 | nsresult rv; |
3806 | *aWindowIDOut = Substring(data, strlen("screen:")).ToInteger64(&rv); |
3807 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3807); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3807; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3808 | return MediaSourceEnum::Screen; |
3809 | } |
3810 | nsresult rv; |
3811 | *aWindowIDOut = data.ToInteger64(&rv); |
3812 | MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType< decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) )))>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1) ))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3812); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" ")"); do { *((volatile int*)__null) = 3812; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3813 | return MediaSourceEnum::Camera; |
3814 | } |
3815 | |
3816 | nsresult MediaManager::Observe(nsISupports* aSubject, const char* aTopic, |
3817 | const char16_t* aData) { |
3818 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 3818; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3819 | |
3820 | MediaMgrError::Name gumNoAccessError = MediaMgrError::Name::NotAllowedError; |
3821 | |
3822 | if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID"nsPref:changed")) { |
3823 | nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(aSubject)); |
3824 | if (branch) { |
3825 | GetPrefs(branch, NS_ConvertUTF16toUTF8(aData).get()); |
3826 | DeviceListChanged(); |
3827 | } |
3828 | } else if (!strcmp(aTopic, "last-pb-context-exited")) { |
3829 | // Clear memory of private-browsing-specific deviceIds. Fire and forget. |
3830 | media::SanitizeOriginKeys(0, true); |
3831 | return NS_OK; |
3832 | } else if (!strcmp(aTopic, "getUserMedia:got-device-permission")) { |
3833 | MOZ_ASSERT(aSubject)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aSubject)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aSubject))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSubject", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSubject" ")" ); do { *((volatile int*)__null) = 3833; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3834 | nsCOMPtr<nsIRunnable> task = do_QueryInterface(aSubject); |
3835 | MediaManager::Dispatch(NewTaskFrom([task] { task->Run(); })); |
3836 | return NS_OK; |
3837 | } else if (!strcmp(aTopic, "getUserMedia:privileged:allow") || |
3838 | !strcmp(aTopic, "getUserMedia:response:allow")) { |
3839 | nsString key(aData); |
3840 | RefPtr<GetUserMediaTask> task = TakeGetUserMediaTask(key); |
3841 | if (!task) { |
3842 | return NS_OK; |
3843 | } |
3844 | |
3845 | if (sHasMainThreadShutdown) { |
3846 | task->Denied(MediaMgrError::Name::AbortError, "In shutdown"_ns); |
3847 | return NS_OK; |
3848 | } |
3849 | if (NS_WARN_IF(!aSubject)NS_warn_if_impl(!aSubject, "!aSubject", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3849)) { |
3850 | return NS_ERROR_FAILURE; // ignored |
3851 | } |
3852 | // Permission has been granted. aSubject contains the particular device |
3853 | // or devices selected and approved by the user, if any. |
3854 | nsCOMPtr<nsIArray> array(do_QueryInterface(aSubject)); |
3855 | MOZ_ASSERT(array)do { static_assert( mozilla::detail::AssertionConditionType< decltype(array)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(array))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("array", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3855); AnnotateMozCrashReason("MOZ_ASSERT" "(" "array" ")") ; do { *((volatile int*)__null) = 3855; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3856 | uint32_t len = 0; |
3857 | array->GetLength(&len); |
3858 | RefPtr<LocalMediaDevice> audioInput; |
3859 | RefPtr<LocalMediaDevice> videoInput; |
3860 | RefPtr<LocalMediaDevice> audioOutput; |
3861 | for (uint32_t i = 0; i < len; i++) { |
3862 | nsCOMPtr<nsIMediaDevice> device; |
3863 | array->QueryElementAt(i, NS_GET_IID(nsIMediaDevice)(nsIMediaDevice::COMTypeInfo<nsIMediaDevice, void>::kIID ), |
3864 | getter_AddRefs(device)); |
3865 | MOZ_ASSERT(device)do { static_assert( mozilla::detail::AssertionConditionType< decltype(device)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(device))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("device", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3865); AnnotateMozCrashReason("MOZ_ASSERT" "(" "device" ")" ); do { *((volatile int*)__null) = 3865; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); // shouldn't be returning anything else... |
3866 | if (!device) { |
3867 | continue; |
3868 | } |
3869 | |
3870 | // Casting here is safe because a LocalMediaDevice is created |
3871 | // only in Gecko side, JS can only query for an instance. |
3872 | auto* dev = static_cast<LocalMediaDevice*>(device.get()); |
3873 | switch (dev->Kind()) { |
3874 | case MediaDeviceKind::Videoinput: |
3875 | if (!videoInput) { |
3876 | videoInput = dev; |
3877 | } |
3878 | break; |
3879 | case MediaDeviceKind::Audioinput: |
3880 | if (!audioInput) { |
3881 | audioInput = dev; |
3882 | } |
3883 | break; |
3884 | case MediaDeviceKind::Audiooutput: |
3885 | if (!audioOutput) { |
3886 | audioOutput = dev; |
3887 | } |
3888 | break; |
3889 | default: |
3890 | MOZ_CRASH("Unexpected device kind")do { do { } while (false); MOZ_ReportCrash("" "Unexpected device kind" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3890); AnnotateMozCrashReason("MOZ_CRASH(" "Unexpected device kind" ")"); do { *((volatile int*)__null) = 3890; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
3891 | } |
3892 | } |
3893 | |
3894 | if (GetUserMediaStreamTask* streamTask = task->AsGetUserMediaStreamTask()) { |
3895 | bool needVideo = IsOn(streamTask->GetConstraints().mVideo); |
3896 | bool needAudio = IsOn(streamTask->GetConstraints().mAudio); |
3897 | MOZ_ASSERT(needVideo || needAudio)do { static_assert( mozilla::detail::AssertionConditionType< decltype(needVideo || needAudio)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(needVideo || needAudio))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("needVideo || needAudio" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3897); AnnotateMozCrashReason("MOZ_ASSERT" "(" "needVideo || needAudio" ")"); do { *((volatile int*)__null) = 3897; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3898 | |
3899 | if ((needVideo && !videoInput) || (needAudio && !audioInput)) { |
3900 | task->Denied(MediaMgrError::Name::NotAllowedError); |
3901 | return NS_OK; |
3902 | } |
3903 | streamTask->Allowed(std::move(audioInput), std::move(videoInput)); |
3904 | return NS_OK; |
3905 | } |
3906 | if (SelectAudioOutputTask* outputTask = task->AsSelectAudioOutputTask()) { |
3907 | if (!audioOutput) { |
3908 | task->Denied(MediaMgrError::Name::NotAllowedError); |
3909 | return NS_OK; |
3910 | } |
3911 | outputTask->Allowed(std::move(audioOutput)); |
3912 | return NS_OK; |
3913 | } |
3914 | |
3915 | NS_WARNING("Unknown task type in getUserMedia")NS_DebugBreak(NS_DEBUG_WARNING, "Unknown task type in getUserMedia" , nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3915); |
3916 | return NS_ERROR_FAILURE; |
3917 | |
3918 | } else if (IsGUMResponseNoAccess(aTopic, gumNoAccessError)) { |
3919 | nsString key(aData); |
3920 | RefPtr<GetUserMediaTask> task = TakeGetUserMediaTask(key); |
3921 | if (task) { |
3922 | task->Denied(gumNoAccessError); |
3923 | SendPendingGUMRequest(); |
3924 | } |
3925 | return NS_OK; |
3926 | |
3927 | } else if (!strcmp(aTopic, "getUserMedia:revoke")) { |
3928 | uint64_t windowID; |
3929 | if (ParseScreenColonWindowID(aData, &windowID) == MediaSourceEnum::Screen) { |
3930 | LOG("Revoking ScreenCapture access for window %" PRIu64"l" "u", windowID); |
3931 | StopScreensharing(windowID); |
3932 | } else { |
3933 | LOG("Revoking MediaCapture access for window %" PRIu64"l" "u", windowID); |
3934 | OnNavigation(windowID); |
3935 | } |
3936 | return NS_OK; |
3937 | } else if (!strcmp(aTopic, "getUserMedia:muteVideo") || |
3938 | !strcmp(aTopic, "getUserMedia:unmuteVideo")) { |
3939 | OnCameraMute(!strcmp(aTopic, "getUserMedia:muteVideo")); |
3940 | return NS_OK; |
3941 | } else if (!strcmp(aTopic, "getUserMedia:muteAudio") || |
3942 | !strcmp(aTopic, "getUserMedia:unmuteAudio")) { |
3943 | OnMicrophoneMute(!strcmp(aTopic, "getUserMedia:muteAudio")); |
3944 | return NS_OK; |
3945 | } else if ((!strcmp(aTopic, "application-background") || |
3946 | !strcmp(aTopic, "application-foreground")) && |
3947 | StaticPrefs::media_getusermedia_camera_background_mute_enabled()) { |
3948 | // On mobile we turn off any cameras (but not mics) while in the background. |
3949 | // Keeping things simple for now by duplicating test-covered code above. |
3950 | // |
3951 | // NOTE: If a mobile device ever wants to implement "getUserMedia:muteVideo" |
3952 | // as well, it'd need to update this code to handle & test the combinations. |
3953 | OnCameraMute(!strcmp(aTopic, "application-background")); |
3954 | } |
3955 | |
3956 | return NS_OK; |
3957 | } |
3958 | |
3959 | NS_IMETHODIMPnsresult |
3960 | MediaManager::CollectReports(nsIHandleReportCallback* aHandleReport, |
3961 | nsISupports* aData, bool aAnonymize) { |
3962 | size_t amount = 0; |
3963 | amount += mActiveWindows.ShallowSizeOfExcludingThis(MallocSizeOf); |
3964 | for (const GetUserMediaWindowListener* listener : mActiveWindows.Values()) { |
3965 | amount += listener->SizeOfIncludingThis(MallocSizeOf); |
3966 | } |
3967 | amount += mActiveCallbacks.ShallowSizeOfExcludingThis(MallocSizeOf); |
3968 | for (const GetUserMediaTask* task : mActiveCallbacks.Values()) { |
3969 | // Assume nsString buffers for keys are accounted in mCallIds. |
3970 | amount += task->SizeOfIncludingThis(MallocSizeOf); |
3971 | } |
3972 | amount += mCallIds.ShallowSizeOfExcludingThis(MallocSizeOf); |
3973 | for (const auto& array : mCallIds.Values()) { |
3974 | amount += array->ShallowSizeOfExcludingThis(MallocSizeOf); |
3975 | for (const nsString& callID : *array) { |
3976 | amount += callID.SizeOfExcludingThisEvenIfShared(MallocSizeOf); |
3977 | } |
3978 | } |
3979 | amount += mPendingGUMRequest.ShallowSizeOfExcludingThis(MallocSizeOf); |
3980 | // GetUserMediaRequest pointees of mPendingGUMRequest do not have support |
3981 | // for memory accounting. mPendingGUMRequest logic should probably be moved |
3982 | // to the front end (bug 1691625). |
3983 | MOZ_COLLECT_REPORT("explicit/media/media-manager-aggregates", KIND_HEAP,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/media/media-manager-aggregates" ), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by MediaManager variable length members." ), aData) |
3984 | UNITS_BYTES, amount,(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/media/media-manager-aggregates" ), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by MediaManager variable length members." ), aData) |
3985 | "Memory used by MediaManager variable length members.")(void)aHandleReport->Callback(""_ns, nsLiteralCString("explicit/media/media-manager-aggregates" ), KIND_HEAP, UNITS_BYTES, amount, nsLiteralCString("Memory used by MediaManager variable length members." ), aData); |
3986 | return NS_OK; |
3987 | } |
3988 | |
3989 | nsresult MediaManager::GetActiveMediaCaptureWindows(nsIArray** aArray) { |
3990 | MOZ_ASSERT(aArray)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aArray)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aArray))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aArray", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 3990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aArray" ")" ); do { *((volatile int*)__null) = 3990; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
3991 | |
3992 | nsCOMPtr<nsIMutableArray> array = nsArray::Create(); |
3993 | |
3994 | for (const auto& entry : mActiveWindows) { |
3995 | const uint64_t& id = entry.GetKey(); |
3996 | RefPtr<GetUserMediaWindowListener> winListener = entry.GetData(); |
3997 | if (!winListener) { |
3998 | continue; |
3999 | } |
4000 | |
4001 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(id); |
4002 | MOZ_ASSERT(window)do { static_assert( mozilla::detail::AssertionConditionType< decltype(window)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(window))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("window", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4002); AnnotateMozCrashReason("MOZ_ASSERT" "(" "window" ")" ); do { *((volatile int*)__null) = 4002; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4003 | // XXXkhuey ... |
4004 | if (!window) { |
4005 | continue; |
4006 | } |
4007 | |
4008 | if (winListener->CapturingVideo() || winListener->CapturingAudio()) { |
4009 | array->AppendElement(ToSupports(window)); |
4010 | } |
4011 | } |
4012 | |
4013 | array.forget(aArray); |
4014 | return NS_OK; |
4015 | } |
4016 | |
4017 | struct CaptureWindowStateData { |
4018 | uint16_t* mCamera; |
4019 | uint16_t* mMicrophone; |
4020 | uint16_t* mScreenShare; |
4021 | uint16_t* mWindowShare; |
4022 | uint16_t* mAppShare; |
4023 | uint16_t* mBrowserShare; |
4024 | }; |
4025 | |
4026 | NS_IMETHODIMPnsresult |
4027 | MediaManager::MediaCaptureWindowState( |
4028 | nsIDOMWindow* aCapturedWindow, uint16_t* aCamera, uint16_t* aMicrophone, |
4029 | uint16_t* aScreen, uint16_t* aWindow, uint16_t* aBrowser, |
4030 | nsTArray<RefPtr<nsIMediaDevice>>& aDevices) { |
4031 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4031; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4032 | |
4033 | CaptureState camera = CaptureState::Off; |
4034 | CaptureState microphone = CaptureState::Off; |
4035 | CaptureState screen = CaptureState::Off; |
4036 | CaptureState window = CaptureState::Off; |
4037 | CaptureState browser = CaptureState::Off; |
4038 | RefPtr<LocalMediaDeviceSetRefCnt> devices; |
4039 | |
4040 | nsCOMPtr<nsPIDOMWindowInner> piWin = do_QueryInterface(aCapturedWindow); |
4041 | if (piWin) { |
4042 | if (RefPtr<GetUserMediaWindowListener> listener = |
4043 | GetWindowListener(piWin->WindowID())) { |
4044 | camera = listener->CapturingSource(MediaSourceEnum::Camera); |
4045 | microphone = listener->CapturingSource(MediaSourceEnum::Microphone); |
4046 | screen = listener->CapturingSource(MediaSourceEnum::Screen); |
4047 | window = listener->CapturingSource(MediaSourceEnum::Window); |
4048 | browser = listener->CapturingSource(MediaSourceEnum::Browser); |
4049 | devices = listener->GetDevices(); |
4050 | } |
4051 | } |
4052 | |
4053 | *aCamera = FromCaptureState(camera); |
4054 | *aMicrophone = FromCaptureState(microphone); |
4055 | *aScreen = FromCaptureState(screen); |
4056 | *aWindow = FromCaptureState(window); |
4057 | *aBrowser = FromCaptureState(browser); |
4058 | if (devices) { |
4059 | for (auto& device : *devices) { |
4060 | aDevices.AppendElement(device); |
4061 | } |
4062 | } |
4063 | |
4064 | LOG("%s: window %" PRIu64"l" "u" " capturing %s %s %s %s %s", __FUNCTION__, |
4065 | piWin ? piWin->WindowID() : -1, |
4066 | *aCamera == nsIMediaManagerService::STATE_CAPTURE_ENABLED |
4067 | ? "camera (enabled)" |
4068 | : (*aCamera == nsIMediaManagerService::STATE_CAPTURE_DISABLED |
4069 | ? "camera (disabled)" |
4070 | : ""), |
4071 | *aMicrophone == nsIMediaManagerService::STATE_CAPTURE_ENABLED |
4072 | ? "microphone (enabled)" |
4073 | : (*aMicrophone == nsIMediaManagerService::STATE_CAPTURE_DISABLED |
4074 | ? "microphone (disabled)" |
4075 | : ""), |
4076 | *aScreen ? "screenshare" : "", *aWindow ? "windowshare" : "", |
4077 | *aBrowser ? "browsershare" : ""); |
4078 | |
4079 | return NS_OK; |
4080 | } |
4081 | |
4082 | NS_IMETHODIMPnsresult |
4083 | MediaManager::SanitizeDeviceIds(int64_t aSinceWhen) { |
4084 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4084); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4084; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4085 | LOG("%s: sinceWhen = %" PRId64"l" "d", __FUNCTION__, aSinceWhen); |
4086 | |
4087 | media::SanitizeOriginKeys(aSinceWhen, false); // we fire and forget |
4088 | return NS_OK; |
4089 | } |
4090 | |
4091 | void MediaManager::StopScreensharing(uint64_t aWindowID) { |
4092 | // We need to stop window/screensharing for all streams in this innerwindow. |
4093 | |
4094 | if (RefPtr<GetUserMediaWindowListener> listener = |
4095 | GetWindowListener(aWindowID)) { |
4096 | listener->StopSharing(); |
4097 | } |
4098 | } |
4099 | |
4100 | bool MediaManager::IsActivelyCapturingOrHasAPermission(uint64_t aWindowId) { |
4101 | // Does page currently have a gUM stream active? |
4102 | |
4103 | nsCOMPtr<nsIArray> array; |
4104 | GetActiveMediaCaptureWindows(getter_AddRefs(array)); |
4105 | uint32_t len; |
4106 | array->GetLength(&len); |
4107 | for (uint32_t i = 0; i < len; i++) { |
4108 | nsCOMPtr<nsPIDOMWindowInner> win; |
4109 | array->QueryElementAt(i, NS_GET_IID(nsPIDOMWindowInner)(nsPIDOMWindowInner::COMTypeInfo<nsPIDOMWindowInner, void> ::kIID), |
4110 | getter_AddRefs(win)); |
4111 | if (win && win->WindowID() == aWindowId) { |
4112 | return true; |
4113 | } |
4114 | } |
4115 | |
4116 | // Or are persistent permissions (audio or video) granted? |
4117 | |
4118 | return GetPersistentPermissions(aWindowId) |
4119 | .map([](auto&& aState) { |
4120 | return aState.mMicrophonePermission == |
4121 | PersistentPermissionState::Allow || |
4122 | aState.mCameraPermission == PersistentPermissionState::Allow; |
4123 | }) |
4124 | .unwrapOr(false); |
4125 | } |
4126 | |
4127 | DeviceListener::DeviceListener() |
4128 | : mStopped(false), |
4129 | mMainThreadCheck(nullptr), |
4130 | mPrincipalHandle(PRINCIPAL_HANDLE_NONEnullptr), |
4131 | mWindowListener(nullptr) {} |
4132 | |
4133 | void DeviceListener::Register(GetUserMediaWindowListener* aListener) { |
4134 | LOG("DeviceListener %p registering with window listener %p", this, aListener); |
4135 | |
4136 | MOZ_ASSERT(aListener, "No listener")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aListener" " (" "No listener" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aListener" ") (" "No listener" ")"); do { *((volatile int*)__null) = 4136; __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
4137 | MOZ_ASSERT(!mWindowListener, "Already registered")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mWindowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mWindowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mWindowListener" " (" "Already registered" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4137); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mWindowListener" ") (" "Already registered" ")"); do { *((volatile int*)__null ) = 4137; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4138 | MOZ_ASSERT(!Activated(), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!Activated()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!Activated()" " (" "Already activated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!Activated()" ") (" "Already activated" ")"); do { *((volatile int*)__null ) = 4138; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4139 | |
4140 | mPrincipalHandle = aListener->GetPrincipalHandle(); |
4141 | mWindowListener = aListener; |
4142 | } |
4143 | |
4144 | void DeviceListener::Activate(RefPtr<LocalMediaDevice> aDevice, |
4145 | RefPtr<LocalTrackSource> aTrackSource, |
4146 | bool aStartMuted) { |
4147 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4147); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4147; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4148 | |
4149 | LOG("DeviceListener %p activating %s device %p", this, |
4150 | dom::GetEnumString(aDevice->Kind()).get(), aDevice.get()); |
4151 | |
4152 | MOZ_ASSERT(!mStopped, "Cannot activate stopped device listener")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mStopped" " (" "Cannot activate stopped device listener" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mStopped" ") (" "Cannot activate stopped device listener" ")"); do { *((volatile int*)__null) = 4152; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4153 | MOZ_ASSERT(!Activated(), "Already activated")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!Activated()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!Activated()" " (" "Already activated" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!Activated()" ") (" "Already activated" ")"); do { *((volatile int*)__null ) = 4153; __attribute__((nomerge)) ::abort(); } while (false) ; } } while (false); |
4154 | |
4155 | mMainThreadCheck = PR_GetCurrentThread(); |
4156 | bool offWhileDisabled = |
4157 | (aDevice->GetMediaSource() == MediaSourceEnum::Microphone && |
4158 | Preferences::GetBool( |
4159 | "media.getusermedia.microphone.off_while_disabled.enabled", true)) || |
4160 | (aDevice->GetMediaSource() == MediaSourceEnum::Camera && |
4161 | Preferences::GetBool( |
4162 | "media.getusermedia.camera.off_while_disabled.enabled", true)); |
4163 | |
4164 | if (MediaEventSource<void>* event = aDevice->Source()->CaptureEndedEvent()) { |
4165 | mCaptureEndedListener = event->Connect(AbstractThread::MainThread(), this, |
4166 | &DeviceListener::Stop); |
4167 | } |
4168 | |
4169 | mDeviceState = MakeUnique<DeviceState>( |
4170 | std::move(aDevice), std::move(aTrackSource), offWhileDisabled); |
4171 | mDeviceState->mDeviceMuted = aStartMuted; |
4172 | if (aStartMuted) { |
4173 | mDeviceState->mTrackSource->Mute(); |
4174 | } |
4175 | } |
4176 | |
4177 | RefPtr<DeviceListener::DeviceListenerPromise> |
4178 | DeviceListener::InitializeAsync() { |
4179 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4179; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4180 | MOZ_DIAGNOSTIC_ASSERT(!mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mStopped))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mStopped", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4180); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mStopped" ")"); do { *((volatile int*)__null) = 4180; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4181 | |
4182 | return MediaManager::Dispatch<DeviceListenerPromise>( |
4183 | __func__, |
4184 | [principal = GetPrincipalHandle(), device = mDeviceState->mDevice, |
4185 | track = mDeviceState->mTrackSource->mTrack, |
4186 | deviceMuted = mDeviceState->mDeviceMuted]( |
4187 | MozPromiseHolder<DeviceListenerPromise>& aHolder) { |
4188 | auto kind = device->Kind(); |
4189 | device->SetTrack(track, principal); |
4190 | nsresult rv = deviceMuted ? NS_OK : device->Start(); |
4191 | if (kind == MediaDeviceKind::Audioinput || |
4192 | kind == MediaDeviceKind::Videoinput) { |
4193 | if ((rv == NS_ERROR_NOT_AVAILABLE && |
4194 | kind == MediaDeviceKind::Audioinput) || |
4195 | (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && kind == MediaDeviceKind::Videoinput)) { |
4196 | PR_Sleep(200); |
4197 | rv = device->Start(); |
4198 | } |
4199 | if (rv == NS_ERROR_NOT_AVAILABLE && |
4200 | kind == MediaDeviceKind::Audioinput) { |
4201 | nsCString log; |
4202 | log.AssignLiteral("Concurrent mic process limit."); |
4203 | aHolder.Reject(MakeRefPtr<MediaMgrError>( |
4204 | MediaMgrError::Name::NotReadableError, |
4205 | std::move(log)), |
4206 | __func__); |
4207 | return; |
4208 | } |
4209 | } |
4210 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4211 | nsCString log; |
4212 | log.AppendPrintf("Starting %s failed", |
4213 | dom::GetEnumString(kind).get()); |
4214 | aHolder.Reject( |
4215 | MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError, |
4216 | std::move(log)), |
4217 | __func__); |
4218 | return; |
4219 | } |
4220 | LOG("started %s device %p", dom::GetEnumString(kind).get(), |
4221 | device.get()); |
4222 | aHolder.Resolve(true, __func__); |
4223 | }) |
4224 | ->Then( |
4225 | GetMainThreadSerialEventTarget(), __func__, |
4226 | [self = RefPtr<DeviceListener>(this), this]() { |
4227 | if (mStopped) { |
4228 | // We were shut down during the async init |
4229 | return DeviceListenerPromise::CreateAndResolve(true, __func__); |
4230 | } |
4231 | |
4232 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mTrackEnabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mTrackEnabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mTrackEnabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mDeviceState->mTrackEnabled", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4232); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mTrackEnabled" ")"); do { *((volatile int*)__null) = 4232; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4233 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mDeviceEnabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mDeviceEnabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mDeviceEnabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mDeviceState->mDeviceEnabled", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4233); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mDeviceEnabled" ")"); do { *((volatile int*)__null) = 4233; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4234 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mStopped)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDeviceState->mStopped" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4234); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mStopped" ")"); do { *((volatile int*)__null) = 4234; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4235 | |
4236 | mDeviceState->mDeviceEnabled = true; |
4237 | mDeviceState->mTrackEnabled = true; |
4238 | mDeviceState->mTrackEnabledTime = TimeStamp::Now(); |
4239 | return DeviceListenerPromise::CreateAndResolve(true, __func__); |
4240 | }, |
4241 | [self = RefPtr<DeviceListener>(this), |
4242 | this](RefPtr<MediaMgrError>&& aResult) { |
4243 | if (mStopped) { |
4244 | return DeviceListenerPromise::CreateAndReject(std::move(aResult), |
4245 | __func__); |
4246 | } |
4247 | |
4248 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mTrackEnabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mTrackEnabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mTrackEnabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mDeviceState->mTrackEnabled", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4248); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mTrackEnabled" ")"); do { *((volatile int*)__null) = 4248; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4249 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mDeviceEnabled)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mDeviceEnabled)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mDeviceEnabled ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!mDeviceState->mDeviceEnabled", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4249); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mDeviceEnabled" ")"); do { *((volatile int*)__null) = 4249; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4250 | MOZ_DIAGNOSTIC_ASSERT(!mDeviceState->mStopped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mDeviceState->mStopped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mDeviceState->mStopped)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDeviceState->mStopped" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4250); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDeviceState->mStopped" ")"); do { *((volatile int*)__null) = 4250; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4251 | |
4252 | Stop(); |
4253 | return DeviceListenerPromise::CreateAndReject(std::move(aResult), |
4254 | __func__); |
4255 | }); |
4256 | } |
4257 | |
4258 | void DeviceListener::Stop() { |
4259 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4259); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4259; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4260 | |
4261 | if (mStopped) { |
4262 | return; |
4263 | } |
4264 | mStopped = true; |
4265 | |
4266 | LOG("DeviceListener %p stopping", this); |
4267 | |
4268 | if (mDeviceState) { |
4269 | mDeviceState->mDisableTimer->Cancel(); |
4270 | |
4271 | if (mDeviceState->mStopped) { |
4272 | // device already stopped. |
4273 | return; |
4274 | } |
4275 | mDeviceState->mStopped = true; |
4276 | |
4277 | mDeviceState->mTrackSource->Stop(); |
4278 | |
4279 | MediaManager::Dispatch(NewTaskFrom([device = mDeviceState->mDevice]() { |
4280 | device->Stop(); |
4281 | device->Deallocate(); |
4282 | })); |
4283 | |
4284 | mWindowListener->ChromeAffectingStateChanged(); |
4285 | } |
4286 | |
4287 | mCaptureEndedListener.DisconnectIfExists(); |
4288 | |
4289 | // Keep a strong ref to the removed window listener. |
4290 | RefPtr<GetUserMediaWindowListener> windowListener = mWindowListener; |
4291 | mWindowListener = nullptr; |
4292 | windowListener->Remove(this); |
4293 | } |
4294 | |
4295 | void DeviceListener::GetSettings(MediaTrackSettings& aOutSettings) const { |
4296 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4296; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4297 | LocalMediaDevice* device = GetDevice(); |
4298 | device->GetSettings(aOutSettings); |
4299 | |
4300 | MediaSourceEnum mediaSource = device->GetMediaSource(); |
4301 | if (mediaSource == MediaSourceEnum::Camera || |
4302 | mediaSource == MediaSourceEnum::Microphone) { |
4303 | aOutSettings.mDeviceId.Construct(device->mID); |
4304 | aOutSettings.mGroupId.Construct(device->mGroupID); |
4305 | } |
4306 | } |
4307 | |
4308 | auto DeviceListener::UpdateDevice(bool aOn) -> RefPtr<DeviceOperationPromise> { |
4309 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4309; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4310 | RefPtr<DeviceListener> self = this; |
4311 | DeviceState& state = *mDeviceState; |
4312 | return MediaManager::Dispatch<DeviceOperationPromise>( |
4313 | __func__, |
4314 | [self, device = state.mDevice, |
4315 | aOn](MozPromiseHolder<DeviceOperationPromise>& h) { |
4316 | LOG("Turning %s device (%s)", aOn ? "on" : "off", |
4317 | NS_ConvertUTF16toUTF8(device->mName).get()); |
4318 | h.Resolve(aOn ? device->Start() : device->Stop(), __func__); |
4319 | }) |
4320 | ->Then( |
4321 | GetMainThreadSerialEventTarget(), __func__, |
4322 | [self, this, &state, aOn](nsresult aResult) { |
4323 | if (state.mStopped) { |
4324 | // Device was stopped on main thread during the operation. Done. |
4325 | return DeviceOperationPromise::CreateAndResolve(aResult, |
4326 | __func__); |
4327 | } |
4328 | LOG("DeviceListener %p turning %s %s input device %s", this, |
4329 | aOn ? "on" : "off", |
4330 | dom::GetEnumString(GetDevice()->Kind()).get(), |
4331 | NS_SUCCEEDED(aResult)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResult)), 1))) ? "succeeded" : "failed"); |
4332 | |
4333 | if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0))) && aResult != NS_ERROR_ABORT) { |
4334 | // This path handles errors from starting or stopping the |
4335 | // device. NS_ERROR_ABORT are for cases where *we* aborted. They |
4336 | // need graceful handling. |
4337 | if (aOn) { |
4338 | // Starting the device failed. Stopping the track here will |
4339 | // make the MediaStreamTrack end after a pass through the |
4340 | // MediaTrackGraph. |
4341 | Stop(); |
4342 | } else { |
4343 | // Stopping the device failed. This is odd, but not fatal. |
4344 | MOZ_ASSERT_UNREACHABLE("The device should be stoppable")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "The device should be stoppable" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The device should be stoppable" ")" ); do { *((volatile int*)__null) = 4344; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4345 | } |
4346 | } |
4347 | return DeviceOperationPromise::CreateAndResolve(aResult, __func__); |
4348 | }, |
4349 | []() { |
4350 | MOZ_ASSERT_UNREACHABLE("Unexpected and unhandled reject")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4350); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject" ")"); do { *((volatile int*)__null) = 4350; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4351 | return DeviceOperationPromise::CreateAndReject(false, __func__); |
4352 | }); |
4353 | } |
4354 | |
4355 | void DeviceListener::SetDeviceEnabled(bool aEnable) { |
4356 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4356); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4356; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4357 | MOZ_ASSERT(Activated(), "No device to set enabled state for")do { static_assert( mozilla::detail::AssertionConditionType< decltype(Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(Activated()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("Activated()" " (" "No device to set enabled state for" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4357); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Activated()" ") (" "No device to set enabled state for" ")"); do { *((volatile int*)__null) = 4357; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4358 | |
4359 | DeviceState& state = *mDeviceState; |
4360 | |
4361 | LOG("DeviceListener %p %s %s device", this, |
4362 | aEnable ? "enabling" : "disabling", |
4363 | dom::GetEnumString(GetDevice()->Kind()).get()); |
4364 | |
4365 | state.mTrackEnabled = aEnable; |
4366 | |
4367 | if (state.mStopped) { |
4368 | // Device terminally stopped. Updating device state is pointless. |
4369 | return; |
4370 | } |
4371 | |
4372 | if (state.mOperationInProgress) { |
4373 | // If a timer is in progress, it needs to be canceled now so the next |
4374 | // DisableTrack() gets a fresh start. Canceling will trigger another |
4375 | // operation. |
4376 | state.mDisableTimer->Cancel(); |
4377 | return; |
4378 | } |
4379 | |
4380 | if (state.mDeviceEnabled == aEnable) { |
4381 | // Device is already in the desired state. |
4382 | return; |
4383 | } |
4384 | |
4385 | // All paths from here on must end in setting |
4386 | // `state.mOperationInProgress` to false. |
4387 | state.mOperationInProgress = true; |
4388 | |
4389 | RefPtr<MediaTimerPromise> timerPromise; |
4390 | if (aEnable) { |
4391 | timerPromise = MediaTimerPromise::CreateAndResolve(true, __func__); |
4392 | state.mTrackEnabledTime = TimeStamp::Now(); |
4393 | } else { |
4394 | const TimeDuration maxDelay = |
4395 | TimeDuration::FromMilliseconds(Preferences::GetUint( |
4396 | GetDevice()->Kind() == MediaDeviceKind::Audioinput |
4397 | ? "media.getusermedia.microphone.off_while_disabled.delay_ms" |
4398 | : "media.getusermedia.camera.off_while_disabled.delay_ms", |
4399 | 3000)); |
4400 | const TimeDuration durationEnabled = |
4401 | TimeStamp::Now() - state.mTrackEnabledTime; |
4402 | const TimeDuration delay = TimeDuration::Max( |
4403 | TimeDuration::FromMilliseconds(0), maxDelay - durationEnabled); |
4404 | timerPromise = state.mDisableTimer->WaitFor(delay, __func__); |
4405 | } |
4406 | |
4407 | RefPtr<DeviceListener> self = this; |
4408 | timerPromise |
4409 | ->Then( |
4410 | GetMainThreadSerialEventTarget(), __func__, |
4411 | [self, this, &state, aEnable]() mutable { |
4412 | MOZ_ASSERT(state.mDeviceEnabled != aEnable,do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mDeviceEnabled != aEnable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled != aEnable ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "state.mDeviceEnabled != aEnable" " (" "Device operation hasn't started" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4413); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled != aEnable" ") (" "Device operation hasn't started" ")"); do { *((volatile int*)__null) = 4413; __attribute__((nomerge)) ::abort(); } while (false); } } while (false) |
4413 | "Device operation hasn't started")do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mDeviceEnabled != aEnable)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled != aEnable ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "state.mDeviceEnabled != aEnable" " (" "Device operation hasn't started" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4413); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled != aEnable" ") (" "Device operation hasn't started" ")"); do { *((volatile int*)__null) = 4413; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4414 | MOZ_ASSERT(state.mOperationInProgress,do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mOperationInProgress)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mOperationInProgress)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mOperationInProgress" " (" "It's our responsibility to reset the inProgress state" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mOperationInProgress" ") (" "It's our responsibility to reset the inProgress state" ")"); do { *((volatile int*)__null) = 4415; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
4415 | "It's our responsibility to reset the inProgress state")do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mOperationInProgress)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mOperationInProgress)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mOperationInProgress" " (" "It's our responsibility to reset the inProgress state" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mOperationInProgress" ") (" "It's our responsibility to reset the inProgress state" ")"); do { *((volatile int*)__null) = 4415; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4416 | |
4417 | LOG("DeviceListener %p %s %s device - starting device operation", |
4418 | this, aEnable ? "enabling" : "disabling", |
4419 | dom::GetEnumString(GetDevice()->Kind()).get()); |
4420 | |
4421 | if (state.mStopped) { |
4422 | // Source was stopped between timer resolving and this runnable. |
4423 | return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT, |
4424 | __func__); |
4425 | } |
4426 | |
4427 | state.mDeviceEnabled = aEnable; |
4428 | |
4429 | if (mWindowListener) { |
4430 | mWindowListener->ChromeAffectingStateChanged(); |
4431 | } |
4432 | if (!state.mOffWhileDisabled || state.mDeviceMuted) { |
4433 | // If the feature to turn a device off while disabled is itself |
4434 | // disabled, or the device is currently user agent muted, then |
4435 | // we shortcut the device operation and tell the |
4436 | // ux-updating code that everything went fine. |
4437 | return DeviceOperationPromise::CreateAndResolve(NS_OK, __func__); |
4438 | } |
4439 | return UpdateDevice(aEnable); |
4440 | }, |
4441 | []() { |
4442 | // Timer was canceled by us. We signal this with NS_ERROR_ABORT. |
4443 | return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT, |
4444 | __func__); |
4445 | }) |
4446 | ->Then( |
4447 | GetMainThreadSerialEventTarget(), __func__, |
4448 | [self, this, &state, aEnable](nsresult aResult) mutable { |
4449 | MOZ_ASSERT_IF(aResult != NS_ERROR_ABORT,do { if (aResult != NS_ERROR_ABORT) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(state.mDeviceEnabled == aEnable)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled == aEnable)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mDeviceEnabled == aEnable" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4450); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled == aEnable" ")"); do { *((volatile int*)__null) = 4450; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
4450 | state.mDeviceEnabled == aEnable)do { if (aResult != NS_ERROR_ABORT) { do { static_assert( mozilla ::detail::AssertionConditionType<decltype(state.mDeviceEnabled == aEnable)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(state.mDeviceEnabled == aEnable)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mDeviceEnabled == aEnable" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4450); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mDeviceEnabled == aEnable" ")"); do { *((volatile int*)__null) = 4450; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
4451 | MOZ_ASSERT(state.mOperationInProgress)do { static_assert( mozilla::detail::AssertionConditionType< decltype(state.mOperationInProgress)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(state.mOperationInProgress)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("state.mOperationInProgress" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "state.mOperationInProgress" ")"); do { *((volatile int*)__null) = 4451; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4452 | state.mOperationInProgress = false; |
4453 | |
4454 | if (state.mStopped) { |
4455 | // Device was stopped on main thread during the operation. |
4456 | // Nothing to do. |
4457 | return; |
4458 | } |
4459 | |
4460 | if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0))) && aResult != NS_ERROR_ABORT && !aEnable) { |
4461 | // To keep our internal state sane in this case, we disallow |
4462 | // future stops due to disable. |
4463 | state.mOffWhileDisabled = false; |
4464 | return; |
4465 | } |
4466 | |
4467 | // This path is for a device operation aResult that was success or |
4468 | // NS_ERROR_ABORT (*we* canceled the operation). |
4469 | // At this point we have to follow up on the intended state, i.e., |
4470 | // update the device state if the track state changed in the |
4471 | // meantime. |
4472 | |
4473 | if (state.mTrackEnabled != state.mDeviceEnabled) { |
4474 | // Track state changed during this operation. We'll start over. |
4475 | SetDeviceEnabled(state.mTrackEnabled); |
4476 | } |
4477 | }, |
4478 | []() { MOZ_ASSERT_UNREACHABLE("Unexpected and unhandled reject")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Unexpected and unhandled reject" ")"); do { *((volatile int*)__null) = 4478; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); }); |
4479 | } |
4480 | |
4481 | void DeviceListener::SetDeviceMuted(bool aMute) { |
4482 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4482); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4482; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4483 | MOZ_ASSERT(Activated(), "No device to set muted state for")do { static_assert( mozilla::detail::AssertionConditionType< decltype(Activated())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(Activated()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("Activated()" " (" "No device to set muted state for" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Activated()" ") (" "No device to set muted state for" ")"); do { *((volatile int*)__null) = 4483; __attribute__((nomerge)) ::abort(); } while (false); } } while (false); |
4484 | |
4485 | DeviceState& state = *mDeviceState; |
4486 | |
4487 | LOG("DeviceListener %p %s %s device", this, aMute ? "muting" : "unmuting", |
4488 | dom::GetEnumString(GetDevice()->Kind()).get()); |
4489 | |
4490 | if (state.mStopped) { |
4491 | // Device terminally stopped. Updating device state is pointless. |
4492 | return; |
4493 | } |
4494 | |
4495 | if (state.mDeviceMuted == aMute) { |
4496 | // Device is already in the desired state. |
4497 | return; |
4498 | } |
4499 | |
4500 | LOG("DeviceListener %p %s %s device - starting device operation", this, |
4501 | aMute ? "muting" : "unmuting", |
4502 | dom::GetEnumString(GetDevice()->Kind()).get()); |
4503 | |
4504 | state.mDeviceMuted = aMute; |
4505 | |
4506 | if (mWindowListener) { |
4507 | mWindowListener->ChromeAffectingStateChanged(); |
4508 | } |
4509 | // Update trackSource to fire mute/unmute events on all its tracks |
4510 | if (aMute) { |
4511 | state.mTrackSource->Mute(); |
4512 | } else { |
4513 | state.mTrackSource->Unmute(); |
4514 | } |
4515 | if (!state.mOffWhileDisabled || !state.mDeviceEnabled) { |
4516 | // If the pref to turn the underlying device is itself off, or the device |
4517 | // is already off, it's unecessary to do anything else. |
4518 | return; |
4519 | } |
4520 | UpdateDevice(!aMute); |
4521 | } |
4522 | |
4523 | void DeviceListener::MuteOrUnmuteCamera(bool aMute) { |
4524 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4524; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4525 | |
4526 | if (mStopped) { |
4527 | return; |
4528 | } |
4529 | |
4530 | MOZ_RELEASE_ASSERT(mWindowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4530); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mWindowListener" ")"); do { *((volatile int*)__null) = 4530; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4531 | LOG("DeviceListener %p MuteOrUnmuteCamera: %s", this, |
4532 | aMute ? "mute" : "unmute"); |
4533 | |
4534 | if (GetDevice() && |
4535 | (GetDevice()->GetMediaSource() == MediaSourceEnum::Camera)) { |
4536 | SetDeviceMuted(aMute); |
4537 | } |
4538 | } |
4539 | |
4540 | void DeviceListener::MuteOrUnmuteMicrophone(bool aMute) { |
4541 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4541; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4542 | |
4543 | if (mStopped) { |
4544 | return; |
4545 | } |
4546 | |
4547 | MOZ_RELEASE_ASSERT(mWindowListener)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mWindowListener)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mWindowListener))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mWindowListener" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4547); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mWindowListener" ")"); do { *((volatile int*)__null) = 4547; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4548 | LOG("DeviceListener %p MuteOrUnmuteMicrophone: %s", this, |
4549 | aMute ? "mute" : "unmute"); |
4550 | |
4551 | if (GetDevice() && |
4552 | (GetDevice()->GetMediaSource() == MediaSourceEnum::Microphone)) { |
4553 | SetDeviceMuted(aMute); |
4554 | } |
4555 | } |
4556 | |
4557 | bool DeviceListener::CapturingVideo() const { |
4558 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4558; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4559 | return Activated() && mDeviceState && !mDeviceState->mStopped && |
4560 | MediaEngineSource::IsVideo(GetDevice()->GetMediaSource()) && |
4561 | (!GetDevice()->IsFake() || |
4562 | Preferences::GetBool("media.navigator.permission.fake")); |
4563 | } |
4564 | |
4565 | bool DeviceListener::CapturingAudio() const { |
4566 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4566); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4566; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4567 | return Activated() && mDeviceState && !mDeviceState->mStopped && |
4568 | MediaEngineSource::IsAudio(GetDevice()->GetMediaSource()) && |
4569 | (!GetDevice()->IsFake() || |
4570 | Preferences::GetBool("media.navigator.permission.fake")); |
4571 | } |
4572 | |
4573 | CaptureState DeviceListener::CapturingSource(MediaSourceEnum aSource) const { |
4574 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4574; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4575 | if (GetDevice()->GetMediaSource() != aSource) { |
4576 | // This DeviceListener doesn't capture a matching source |
4577 | return CaptureState::Off; |
4578 | } |
4579 | |
4580 | if (mDeviceState->mStopped) { |
4581 | // The source is a match but has been permanently stopped |
4582 | return CaptureState::Off; |
4583 | } |
4584 | |
4585 | if ((aSource == MediaSourceEnum::Camera || |
4586 | aSource == MediaSourceEnum::Microphone) && |
4587 | GetDevice()->IsFake() && |
4588 | !Preferences::GetBool("media.navigator.permission.fake")) { |
4589 | // Fake Camera and Microphone only count if there is no fake permission |
4590 | return CaptureState::Off; |
4591 | } |
4592 | |
4593 | // Source is a match and is active and unmuted |
4594 | |
4595 | if (mDeviceState->mDeviceEnabled && !mDeviceState->mDeviceMuted) { |
4596 | return CaptureState::Enabled; |
4597 | } |
4598 | |
4599 | return CaptureState::Disabled; |
4600 | } |
4601 | |
4602 | RefPtr<DeviceListener::DeviceListenerPromise> DeviceListener::ApplyConstraints( |
4603 | const MediaTrackConstraints& aConstraints, CallerType aCallerType) { |
4604 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4604; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4605 | |
4606 | if (mStopped || mDeviceState->mStopped) { |
4607 | LOG("DeviceListener %p %s device applyConstraints, but device is stopped", |
4608 | this, dom::GetEnumString(GetDevice()->Kind()).get()); |
4609 | return DeviceListenerPromise::CreateAndResolve(false, __func__); |
4610 | } |
4611 | |
4612 | MediaManager* mgr = MediaManager::GetIfExists(); |
4613 | if (!mgr) { |
4614 | return DeviceListenerPromise::CreateAndResolve(false, __func__); |
4615 | } |
4616 | |
4617 | return MediaManager::Dispatch<DeviceListenerPromise>( |
4618 | __func__, [device = mDeviceState->mDevice, aConstraints, aCallerType]( |
4619 | MozPromiseHolder<DeviceListenerPromise>& aHolder) mutable { |
4620 | MOZ_ASSERT(MediaManager::IsInMediaThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(MediaManager::IsInMediaThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(MediaManager::IsInMediaThread ()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("MediaManager::IsInMediaThread()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "MediaManager::IsInMediaThread()" ")"); do { *((volatile int*)__null) = 4620; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4621 | MediaManager* mgr = MediaManager::GetIfExists(); |
4622 | MOZ_RELEASE_ASSERT(mgr)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mgr)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(mgr))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("mgr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4622); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mgr" ")"); do { *((volatile int*)__null) = 4622; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); // Must exist while media thread is alive |
4623 | const char* badConstraint = nullptr; |
4624 | nsresult rv = |
4625 | device->Reconfigure(aConstraints, mgr->mPrefs, &badConstraint); |
4626 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4627 | if (rv == NS_ERROR_INVALID_ARG) { |
4628 | // Reconfigure failed due to constraints |
4629 | if (!badConstraint) { |
4630 | nsTArray<RefPtr<LocalMediaDevice>> devices; |
4631 | devices.AppendElement(device); |
4632 | badConstraint = MediaConstraintsHelper::SelectSettings( |
4633 | NormalizedConstraints(aConstraints), devices, aCallerType); |
4634 | } |
4635 | } else { |
4636 | // Unexpected. ApplyConstraints* cannot fail with any other error. |
4637 | badConstraint = ""; |
4638 | LOG("ApplyConstraints-Task: Unexpected fail %" PRIx32"x", |
4639 | static_cast<uint32_t>(rv)); |
4640 | } |
4641 | |
4642 | aHolder.Reject(MakeRefPtr<MediaMgrError>( |
4643 | MediaMgrError::Name::OverconstrainedError, "", |
4644 | NS_ConvertASCIItoUTF16(badConstraint)), |
4645 | __func__); |
4646 | return; |
4647 | } |
4648 | // Reconfigure was successful |
4649 | aHolder.Resolve(false, __func__); |
4650 | }); |
4651 | } |
4652 | |
4653 | PrincipalHandle DeviceListener::GetPrincipalHandle() const { |
4654 | return mPrincipalHandle; |
4655 | } |
4656 | |
4657 | void GetUserMediaWindowListener::StopSharing() { |
4658 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4658); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4658; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4659 | |
4660 | for (auto& l : mActiveListeners.Clone()) { |
4661 | MediaSourceEnum source = l->GetDevice()->GetMediaSource(); |
4662 | if (source == MediaSourceEnum::Screen || |
4663 | source == MediaSourceEnum::Window || |
4664 | source == MediaSourceEnum::AudioCapture) { |
4665 | l->Stop(); |
4666 | } |
4667 | } |
4668 | } |
4669 | |
4670 | void GetUserMediaWindowListener::StopRawID(const nsString& removedDeviceID) { |
4671 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4671; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4672 | |
4673 | for (auto& l : mActiveListeners.Clone()) { |
4674 | if (removedDeviceID.Equals(l->GetDevice()->RawID())) { |
4675 | l->Stop(); |
4676 | } |
4677 | } |
4678 | } |
4679 | |
4680 | void GetUserMediaWindowListener::MuteOrUnmuteCameras(bool aMute) { |
4681 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4681; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4682 | |
4683 | if (mCamerasAreMuted == aMute) { |
4684 | return; |
4685 | } |
4686 | mCamerasAreMuted = aMute; |
4687 | |
4688 | for (auto& l : mActiveListeners) { |
4689 | if (l->GetDevice()->Kind() == MediaDeviceKind::Videoinput) { |
4690 | l->MuteOrUnmuteCamera(aMute); |
4691 | } |
4692 | } |
4693 | } |
4694 | |
4695 | void GetUserMediaWindowListener::MuteOrUnmuteMicrophones(bool aMute) { |
4696 | MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread")do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" " (" "Only call on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ") (" "Only call on main thread" ")"); do { *((volatile int* )__null) = 4696; __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
4697 | |
4698 | if (mMicrophonesAreMuted == aMute) { |
4699 | return; |
4700 | } |
4701 | mMicrophonesAreMuted = aMute; |
4702 | |
4703 | for (auto& l : mActiveListeners) { |
4704 | if (l->GetDevice()->Kind() == MediaDeviceKind::Audioinput) { |
4705 | l->MuteOrUnmuteMicrophone(aMute); |
4706 | } |
4707 | } |
4708 | } |
4709 | |
4710 | void GetUserMediaWindowListener::ChromeAffectingStateChanged() { |
4711 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 4711; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4712 | |
4713 | // We wait until stable state before notifying chrome so chrome only does |
4714 | // one update if more updates happen in this event loop. |
4715 | |
4716 | if (mChromeNotificationTaskPosted) { |
4717 | return; |
4718 | } |
4719 | |
4720 | nsCOMPtr<nsIRunnable> runnable = |
4721 | NewRunnableMethod("GetUserMediaWindowListener::NotifyChrome", this, |
4722 | &GetUserMediaWindowListener::NotifyChrome); |
4723 | nsContentUtils::RunInStableState(runnable.forget()); |
4724 | mChromeNotificationTaskPosted = true; |
4725 | } |
4726 | |
4727 | void GetUserMediaWindowListener::NotifyChrome() { |
4728 | MOZ_ASSERT(mChromeNotificationTaskPosted)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mChromeNotificationTaskPosted)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mChromeNotificationTaskPosted ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "mChromeNotificationTaskPosted", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChromeNotificationTaskPosted" ")"); do { *((volatile int*)__null) = 4728; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4729 | mChromeNotificationTaskPosted = false; |
4730 | |
4731 | NS_DispatchToMainThread(NS_NewRunnableFunction( |
4732 | "MediaManager::NotifyChrome", [windowID = mWindowID]() { |
4733 | auto* window = nsGlobalWindowInner::GetInnerWindowWithId(windowID); |
4734 | if (!window) { |
4735 | MOZ_ASSERT_UNREACHABLE("Should have window")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Should have window" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4735); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Should have window" ")"); do { * ((volatile int*)__null) = 4735; __attribute__((nomerge)) ::abort (); } while (false); } } while (false); |
4736 | return; |
4737 | } |
4738 | |
4739 | nsresult rv = MediaManager::NotifyRecordingStatusChange(window); |
4740 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
4741 | MOZ_ASSERT_UNREACHABLE("Should be able to notify chrome")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "Should be able to notify chrome" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/MediaManager.cpp" , 4741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "Should be able to notify chrome" ")"); do { *((volatile int*)__null) = 4741; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
4742 | return; |
4743 | } |
4744 | })); |
4745 | } |
4746 | |
4747 | #undef LOG |
4748 | |
4749 | } // namespace mozilla |