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