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