1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef MOZILLA_MEDIAMANAGER_H
6 #define MOZILLA_MEDIAMANAGER_H
8 #include "MediaEngine.h"
9 #include "MediaEnginePrefs.h"
10 #include "mozilla/media/DeviceChangeCallback.h"
11 #include "mozilla/dom/GetUserMediaRequest.h"
12 #include "mozilla/Services.h"
13 #include "mozilla/Unused.h"
14 #include "nsAutoPtr.h"
15 #include "nsIMediaManager.h"
17 #include "nsHashKeys.h"
18 #include "nsClassHashtable.h"
19 #include "nsRefPtrHashtable.h"
20 #include "nsIObserver.h"
21 #include "nsIPrefService.h"
22 #include "nsIPrefBranch.h"
24 #include "nsIDOMNavigatorUserMedia.h"
25 #include "nsXULAppAPI.h"
26 #include "mozilla/Attributes.h"
27 #include "mozilla/Preferences.h"
28 #include "mozilla/StaticPtr.h"
29 #include "mozilla/dom/MediaStreamBinding.h"
30 #include "mozilla/dom/MediaStreamTrackBinding.h"
31 #include "mozilla/dom/MediaStreamError.h"
32 #include "mozilla/media/MediaChild.h"
33 #include "mozilla/media/MediaParent.h"
34 #include "mozilla/Logging.h"
35 #include "mozilla/UniquePtr.h"
36 #include "DOMMediaStream.h"
39 #include "mtransport/runnable_utils.h"
42 // Note, these suck in Windows headers, unfortunately.
43 #include "base/thread.h"
44 #include "base/task.h"
48 struct MediaStreamConstraints
;
49 struct MediaTrackConstraints
;
50 struct MediaTrackConstraintSet
;
51 enum class CallerType
: uint32_t;
58 class AllocationHandle
;
59 class GetUserMediaTask
;
60 class GetUserMediaWindowListener
;
64 LogModule
* GetMediaManagerLog();
66 class MediaDevice
: public nsIMediaDevice
69 NS_DECL_THREADSAFE_ISUPPORTS
70 NS_DECL_NSIMEDIADEVICE
72 explicit MediaDevice(MediaEngineSource
* aSource
,
73 const nsString
& aName
,
75 const nsString
& aRawID
= NS_LITERAL_STRING(""));
77 uint32_t GetBestFitnessDistance(
78 const nsTArray
<const NormalizedConstraintSet
*>& aConstraintSets
,
81 nsresult
Allocate(const dom::MediaTrackConstraints
& aConstraints
,
82 const MediaEnginePrefs
& aPrefs
,
83 const mozilla::ipc::PrincipalInfo
& aPrincipalInfo
,
84 const char** aOutBadConstraint
);
85 nsresult
SetTrack(const RefPtr
<SourceMediaStream
>& aStream
,
87 const PrincipalHandle
& aPrincipal
);
89 nsresult
Reconfigure(const dom::MediaTrackConstraints
& aConstraints
,
90 const MediaEnginePrefs
& aPrefs
,
91 const char** aOutBadConstraint
);
93 nsresult
Deallocate();
95 void Pull(const RefPtr
<SourceMediaStream
>& aStream
,
97 StreamTime aDesiredTime
,
98 const PrincipalHandle
& aPrincipal
);
100 void GetSettings(dom::MediaTrackSettings
& aOutSettings
) const;
102 dom::MediaSourceEnum
GetMediaSource() const;
104 virtual ~MediaDevice() = default;
106 static uint32_t FitnessDistance(nsString aN
,
107 const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters
& aConstraint
);
109 static bool StringsContain(const dom::OwningStringOrStringSequence
& aStrings
,
111 static uint32_t FitnessDistance(nsString aN
,
112 const dom::ConstrainDOMStringParameters
& aParams
);
114 // Assigned on allocation on media thread, then read on the media thread and
116 RefPtr
<AllocationHandle
> mAllocationHandle
;
119 const RefPtr
<MediaEngineSource
> mSource
;
122 const nsString mType
;
123 const nsString mName
;
125 const nsString mRawID
;
128 typedef nsRefPtrHashtable
<nsUint64HashKey
, GetUserMediaWindowListener
> WindowTable
;
130 class MediaManager final
: public nsIMediaManagerService
,
132 ,public DeviceChangeCallback
134 friend SourceListener
;
136 static already_AddRefed
<MediaManager
> GetInstance();
138 // NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
139 // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
140 // from MediaManager thread.
141 static MediaManager
* Get();
142 static MediaManager
* GetIfExists();
143 static void StartupInit();
144 static void PostTask(already_AddRefed
<Runnable
> task
);
147 * Posts an async operation to the media manager thread.
148 * FunctionType must be a function that takes a `MozPromiseHolder&`.
150 * The returned promise is resolved or rejected by aFunction on the media
153 template<typename MozPromiseType
, typename FunctionType
>
154 static RefPtr
<MozPromiseType
>
155 PostTask(const char* aName
, FunctionType
&& aFunction
);
158 static bool IsInMediaThread();
166 static nsresult
NotifyRecordingStatusChange(nsPIDOMWindowInner
* aWindow
);
168 NS_DECL_THREADSAFE_ISUPPORTS
170 NS_DECL_NSIMEDIAMANAGERSERVICE
172 media::Parent
<media::NonE10s
>* GetNonE10sParent();
173 MediaEngine
* GetBackend(uint64_t aWindowId
= 0);
175 WindowTable
*GetActiveWindows() {
176 MOZ_ASSERT(NS_IsMainThread());
177 return &mActiveWindows
;
179 GetUserMediaWindowListener
*GetWindowListener(uint64_t aWindowId
) {
180 MOZ_ASSERT(NS_IsMainThread());
181 return mActiveWindows
.GetWeak(aWindowId
);
183 void AddWindowID(uint64_t aWindowId
, GetUserMediaWindowListener
*aListener
);
184 void RemoveWindowID(uint64_t aWindowId
);
185 void SendPendingGUMRequest();
186 bool IsWindowStillActive(uint64_t aWindowId
) {
187 return !!GetWindowListener(aWindowId
);
189 bool IsWindowListenerStillActive(GetUserMediaWindowListener
* aListener
);
190 // Note: also calls aListener->Remove(), even if inactive
191 void RemoveFromWindowList(uint64_t aWindowID
,
192 GetUserMediaWindowListener
*aListener
);
194 nsresult
GetUserMedia(
195 nsPIDOMWindowInner
* aWindow
,
196 const dom::MediaStreamConstraints
& aConstraints
,
197 nsIDOMGetUserMediaSuccessCallback
* onSuccess
,
198 nsIDOMGetUserMediaErrorCallback
* onError
,
199 dom::CallerType aCallerType
);
201 nsresult
GetUserMediaDevices(nsPIDOMWindowInner
* aWindow
,
202 const dom::MediaStreamConstraints
& aConstraints
,
203 nsIGetUserMediaDevicesSuccessCallback
* onSuccess
,
204 nsIDOMGetUserMediaErrorCallback
* onError
,
205 uint64_t aInnerWindowID
= 0,
206 const nsAString
& aCallID
= nsString());
208 nsresult
EnumerateDevices(nsPIDOMWindowInner
* aWindow
,
209 nsIGetUserMediaDevicesSuccessCallback
* aOnSuccess
,
210 nsIDOMGetUserMediaErrorCallback
* aOnFailure
,
211 dom::CallerType aCallerType
);
213 nsresult
EnumerateDevices(nsPIDOMWindowInner
* aWindow
, dom::Promise
& aPromise
);
214 void OnNavigation(uint64_t aWindowID
);
215 bool IsActivelyCapturingOrHasAPermission(uint64_t aWindowId
);
217 MediaEnginePrefs mPrefs
;
219 typedef nsTArray
<RefPtr
<MediaDevice
>> SourceSet
;
221 virtual int AddDeviceChangeCallback(DeviceChangeCallback
* aCallback
) override
;
222 virtual void OnDeviceChange() override
;
224 typedef media::Pledge
<SourceSet
*, dom::MediaStreamError
*> PledgeSourceSet
;
225 typedef media::Pledge
<const char*, dom::MediaStreamError
*> PledgeChar
;
226 typedef media::Pledge
<bool, dom::MediaStreamError
*> PledgeVoid
;
228 static nsresult
GenerateUUID(nsAString
& aResult
);
229 static nsresult
AnonymizeId(nsAString
& aId
, const nsACString
& aOriginKey
);
230 public: // TODO: make private once we upgrade to GCC 4.8+ on linux.
231 static void AnonymizeDevices(SourceSet
& aDevices
, const nsACString
& aOriginKey
);
232 static already_AddRefed
<nsIWritableVariant
> ToJSArray(SourceSet
& aDevices
);
234 enum class DeviceEnumerationType
:uint8_t {
235 Normal
, // Enumeration should not return loopback or fake devices
236 Fake
, // Enumeration should return fake device(s)
237 Loopback
/* Enumeration should return loopback device(s) (possibly in
238 addition to normal devices) */
240 already_AddRefed
<PledgeSourceSet
>
241 EnumerateRawDevices(uint64_t aWindowId
,
242 dom::MediaSourceEnum aVideoType
,
243 dom::MediaSourceEnum aAudioType
,
244 DeviceEnumerationType aVideoEnumType
= DeviceEnumerationType::Normal
,
245 DeviceEnumerationType aAudioEnumType
= DeviceEnumerationType::Normal
);
246 already_AddRefed
<PledgeSourceSet
>
247 EnumerateDevicesImpl(uint64_t aWindowId
,
248 dom::MediaSourceEnum aVideoType
,
249 dom::MediaSourceEnum aAudioType
,
250 DeviceEnumerationType aVideoEnumType
= DeviceEnumerationType::Normal
,
251 DeviceEnumerationType aAudioEnumType
= DeviceEnumerationType::Normal
);
252 already_AddRefed
<PledgeChar
>
254 dom::MediaStreamConstraints
& aConstraints
,
256 RefPtr
<media::Refcountable
<UniquePtr
<SourceSet
>>>& aSources
);
258 void GetPref(nsIPrefBranch
*aBranch
, const char *aPref
,
259 const char *aData
, int32_t *aVal
);
260 void GetPrefBool(nsIPrefBranch
*aBranch
, const char *aPref
,
261 const char *aData
, bool *aVal
);
262 void GetPrefs(nsIPrefBranch
*aBranch
, const char *aData
);
264 // Make private because we want only one instance of this class
270 void StopScreensharing(uint64_t aWindowID
);
273 * Calls aCallback with a GetUserMediaWindowListener argument once for
274 * each window listener associated with aWindow and its child windows.
276 template<typename FunctionType
>
277 void IterateWindowListeners(nsPIDOMWindowInner
*aWindow
,
278 const FunctionType
& aCallback
);
280 void StopMediaStreams();
281 void RemoveMediaDevicesCallback(uint64_t aWindowID
);
283 // ONLY access from MainThread so we don't need to lock
284 WindowTable mActiveWindows
;
285 nsRefPtrHashtable
<nsStringHashKey
, GetUserMediaTask
> mActiveCallbacks
;
286 nsClassHashtable
<nsUint64HashKey
, nsTArray
<nsString
>> mCallIds
;
287 nsTArray
<RefPtr
<dom::GetUserMediaRequest
>> mPendingGUMRequest
;
290 nsAutoPtr
<base::Thread
> mMediaThread
;
291 nsCOMPtr
<nsIAsyncShutdownBlocker
> mShutdownBlocker
;
293 // ONLY accessed from MediaManagerThread
294 RefPtr
<MediaEngine
> mBackend
;
296 static StaticRefPtr
<MediaManager
> sSingleton
;
298 media::CoatCheck
<PledgeSourceSet
> mOutstandingPledges
;
299 media::CoatCheck
<PledgeChar
> mOutstandingCharPledges
;
300 nsTArray
<nsString
> mDeviceIDs
;
302 media::CoatCheck
<media::Pledge
<nsCString
>> mGetPrincipalKeyPledges
;
303 RefPtr
<media::Parent
<media::NonE10s
>> mNonE10sParent
;
306 } // namespace mozilla
308 #endif // MOZILLA_MEDIAMANAGER_H