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