Line data Source code
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/. */
4 :
5 : #ifndef MOZILLA_MEDIAMANAGER_H
6 : #define MOZILLA_MEDIAMANAGER_H
7 :
8 : #include "MediaEngine.h"
9 : #include "mozilla/media/DeviceChangeCallback.h"
10 : #include "mozilla/dom/GetUserMediaRequest.h"
11 : #include "mozilla/Services.h"
12 : #include "mozilla/Unused.h"
13 : #include "nsAutoPtr.h"
14 : #include "nsIMediaManager.h"
15 :
16 : #include "nsHashKeys.h"
17 : #include "nsGlobalWindow.h"
18 : #include "nsClassHashtable.h"
19 : #include "nsRefPtrHashtable.h"
20 : #include "nsIObserver.h"
21 : #include "nsIPrefService.h"
22 : #include "nsIPrefBranch.h"
23 :
24 : #include "nsPIDOMWindow.h"
25 : #include "nsIDOMNavigatorUserMedia.h"
26 : #include "nsXULAppAPI.h"
27 : #include "mozilla/Attributes.h"
28 : #include "mozilla/Preferences.h"
29 : #include "mozilla/StaticPtr.h"
30 : #include "mozilla/dom/MediaStreamBinding.h"
31 : #include "mozilla/dom/MediaStreamTrackBinding.h"
32 : #include "mozilla/dom/MediaStreamError.h"
33 : #include "mozilla/media/MediaChild.h"
34 : #include "mozilla/media/MediaParent.h"
35 : #include "mozilla/Logging.h"
36 : #include "mozilla/UniquePtr.h"
37 : #include "DOMMediaStream.h"
38 :
39 : #ifdef MOZ_WEBRTC
40 : #include "mtransport/runnable_utils.h"
41 : #endif
42 :
43 : // Note, these suck in Windows headers, unfortunately.
44 : #include "base/thread.h"
45 : #include "base/task.h"
46 :
47 : namespace mozilla {
48 : namespace dom {
49 : struct MediaStreamConstraints;
50 : struct MediaTrackConstraints;
51 : struct MediaTrackConstraintSet;
52 : enum class CallerType : uint32_t;
53 : } // namespace dom
54 :
55 : namespace ipc {
56 : class PrincipalInfo;
57 : }
58 :
59 : class GetUserMediaTask;
60 : class GetUserMediaWindowListener;
61 : class MediaManager;
62 : class SourceListener;
63 :
64 : class MediaDevice : public nsIMediaDevice
65 : {
66 : public:
67 : typedef MediaEngineSource Source;
68 :
69 : NS_DECL_THREADSAFE_ISUPPORTS
70 : NS_DECL_NSIMEDIADEVICE
71 :
72 : void SetId(const nsAString& aID);
73 : void SetRawId(const nsAString& aID);
74 : virtual uint32_t GetBestFitnessDistance(
75 : const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
76 : bool aIsChrome);
77 : virtual Source* GetSource() = 0;
78 : nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
79 : const MediaEnginePrefs &aPrefs,
80 : const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
81 : const char** aOutBadConstraint);
82 : nsresult Restart(const dom::MediaTrackConstraints &aConstraints,
83 : const MediaEnginePrefs &aPrefs,
84 : const char** aOutBadConstraint);
85 : nsresult Deallocate();
86 : protected:
87 0 : virtual ~MediaDevice() {}
88 : explicit MediaDevice(MediaEngineSource* aSource, bool aIsVideo);
89 :
90 : static uint32_t FitnessDistance(nsString aN,
91 : const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aConstraint);
92 : private:
93 : static bool StringsContain(const dom::OwningStringOrStringSequence& aStrings,
94 : nsString aN);
95 : static uint32_t FitnessDistance(nsString aN,
96 : const dom::ConstrainDOMStringParameters& aParams);
97 : protected:
98 : nsString mName;
99 : nsString mID;
100 : nsString mRawID;
101 : bool mScary;
102 : dom::MediaSourceEnum mMediaSource;
103 : RefPtr<MediaEngineSource> mSource;
104 : RefPtr<MediaEngineSource::AllocationHandle> mAllocationHandle;
105 : public:
106 0 : dom::MediaSourceEnum GetMediaSource() {
107 0 : return mMediaSource;
108 : }
109 : bool mIsVideo;
110 : };
111 :
112 0 : class VideoDevice : public MediaDevice
113 : {
114 : public:
115 : typedef MediaEngineVideoSource Source;
116 :
117 : explicit VideoDevice(Source* aSource);
118 : NS_IMETHOD GetType(nsAString& aType) override;
119 : Source* GetSource() override;
120 : };
121 :
122 0 : class AudioDevice : public MediaDevice
123 : {
124 : public:
125 : typedef MediaEngineAudioSource Source;
126 :
127 : explicit AudioDevice(Source* aSource);
128 : NS_IMETHOD GetType(nsAString& aType) override;
129 : Source* GetSource() override;
130 : };
131 :
132 : class GetUserMediaNotificationEvent: public Runnable
133 : {
134 : public:
135 : enum GetUserMediaStatus {
136 : STARTING,
137 : STOPPING,
138 : };
139 : GetUserMediaNotificationEvent(GetUserMediaStatus aStatus,
140 : uint64_t aWindowID);
141 :
142 : GetUserMediaNotificationEvent(GetUserMediaStatus aStatus,
143 : already_AddRefed<DOMMediaStream> aStream,
144 : already_AddRefed<media::Refcountable<UniquePtr<OnTracksAvailableCallback>>> aOnTracksAvailableCallback,
145 : uint64_t aWindowID,
146 : already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError);
147 : virtual ~GetUserMediaNotificationEvent();
148 :
149 : NS_IMETHOD Run() override;
150 :
151 : protected:
152 : RefPtr<GetUserMediaWindowListener> mListener; // threadsafe
153 : RefPtr<DOMMediaStream> mStream;
154 : RefPtr<media::Refcountable<UniquePtr<OnTracksAvailableCallback>>> mOnTracksAvailableCallback;
155 : GetUserMediaStatus mStatus;
156 : uint64_t mWindowID;
157 : RefPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
158 : };
159 :
160 : typedef enum {
161 : MEDIA_STOP,
162 : MEDIA_STOP_TRACK,
163 : MEDIA_DIRECT_LISTENERS,
164 : } MediaOperation;
165 :
166 0 : class ReleaseMediaOperationResource : public Runnable
167 : {
168 : public:
169 0 : ReleaseMediaOperationResource(
170 : already_AddRefed<DOMMediaStream> aStream,
171 : already_AddRefed<media::Refcountable<UniquePtr<OnTracksAvailableCallback>>>
172 : aOnTracksAvailableCallback)
173 0 : : Runnable("ReleaseMediaOperationResource")
174 : , mStream(aStream)
175 0 : , mOnTracksAvailableCallback(aOnTracksAvailableCallback)
176 : {
177 0 : }
178 0 : NS_IMETHOD Run() override {return NS_OK;}
179 : private:
180 : RefPtr<DOMMediaStream> mStream;
181 : RefPtr<media::Refcountable<UniquePtr<OnTracksAvailableCallback>>> mOnTracksAvailableCallback;
182 : };
183 :
184 : typedef nsRefPtrHashtable<nsUint64HashKey, GetUserMediaWindowListener> WindowTable;
185 :
186 : // we could add MediaManager if needed
187 : typedef void (*WindowListenerCallback)(MediaManager *aThis,
188 : uint64_t aWindowID,
189 : GetUserMediaWindowListener *aListener,
190 : void *aData);
191 :
192 : class MediaManager final : public nsIMediaManagerService,
193 : public nsIObserver
194 : ,public DeviceChangeCallback
195 : {
196 : friend SourceListener;
197 : public:
198 : static already_AddRefed<MediaManager> GetInstance();
199 :
200 : // NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
201 : // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
202 : // from MediaManager thread.
203 : static MediaManager* Get();
204 : static MediaManager* GetIfExists();
205 : static void StartupInit();
206 : static void PostTask(already_AddRefed<Runnable> task);
207 : #ifdef DEBUG
208 : static bool IsInMediaThread();
209 : #endif
210 :
211 4 : static bool Exists()
212 : {
213 4 : return !!sSingleton;
214 : }
215 :
216 : static nsresult NotifyRecordingStatusChange(nsPIDOMWindowInner* aWindow,
217 : const nsString& aMsg);
218 :
219 : NS_DECL_THREADSAFE_ISUPPORTS
220 : NS_DECL_NSIOBSERVER
221 : NS_DECL_NSIMEDIAMANAGERSERVICE
222 :
223 : media::Parent<media::NonE10s>* GetNonE10sParent();
224 : MediaEngine* GetBackend(uint64_t aWindowId = 0);
225 :
226 0 : WindowTable *GetActiveWindows() {
227 0 : MOZ_ASSERT(NS_IsMainThread());
228 0 : return &mActiveWindows;
229 : }
230 0 : GetUserMediaWindowListener *GetWindowListener(uint64_t aWindowId) {
231 0 : MOZ_ASSERT(NS_IsMainThread());
232 0 : return mActiveWindows.GetWeak(aWindowId);
233 : }
234 : void AddWindowID(uint64_t aWindowId, GetUserMediaWindowListener *aListener);
235 : void RemoveWindowID(uint64_t aWindowId);
236 : void SendPendingGUMRequest();
237 0 : bool IsWindowStillActive(uint64_t aWindowId) {
238 0 : return !!GetWindowListener(aWindowId);
239 : }
240 : // Note: also calls aListener->Remove(), even if inactive
241 : void RemoveFromWindowList(uint64_t aWindowID,
242 : GetUserMediaWindowListener *aListener);
243 :
244 : nsresult GetUserMedia(
245 : nsPIDOMWindowInner* aWindow,
246 : const dom::MediaStreamConstraints& aConstraints,
247 : nsIDOMGetUserMediaSuccessCallback* onSuccess,
248 : nsIDOMGetUserMediaErrorCallback* onError,
249 : dom::CallerType aCallerType);
250 :
251 : nsresult GetUserMediaDevices(nsPIDOMWindowInner* aWindow,
252 : const dom::MediaStreamConstraints& aConstraints,
253 : nsIGetUserMediaDevicesSuccessCallback* onSuccess,
254 : nsIDOMGetUserMediaErrorCallback* onError,
255 : uint64_t aInnerWindowID = 0,
256 : const nsAString& aCallID = nsString());
257 :
258 : nsresult EnumerateDevices(nsPIDOMWindowInner* aWindow,
259 : nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
260 : nsIDOMGetUserMediaErrorCallback* aOnFailure);
261 :
262 : nsresult EnumerateDevices(nsPIDOMWindowInner* aWindow, dom::Promise& aPromise);
263 : void OnNavigation(uint64_t aWindowID);
264 : bool IsActivelyCapturingOrHasAPermission(uint64_t aWindowId);
265 :
266 : MediaEnginePrefs mPrefs;
267 :
268 : typedef nsTArray<RefPtr<MediaDevice>> SourceSet;
269 :
270 : virtual int AddDeviceChangeCallback(DeviceChangeCallback* aCallback) override;
271 : virtual void OnDeviceChange() override;
272 : private:
273 : typedef media::Pledge<SourceSet*, dom::MediaStreamError*> PledgeSourceSet;
274 : typedef media::Pledge<const char*, dom::MediaStreamError*> PledgeChar;
275 : typedef media::Pledge<bool, dom::MediaStreamError*> PledgeVoid;
276 :
277 : static nsresult GenerateUUID(nsAString& aResult);
278 : static nsresult AnonymizeId(nsAString& aId, const nsACString& aOriginKey);
279 : public: // TODO: make private once we upgrade to GCC 4.8+ on linux.
280 : static void AnonymizeDevices(SourceSet& aDevices, const nsACString& aOriginKey);
281 : static already_AddRefed<nsIWritableVariant> ToJSArray(SourceSet& aDevices);
282 : private:
283 : already_AddRefed<PledgeSourceSet>
284 : EnumerateRawDevices(uint64_t aWindowId,
285 : dom::MediaSourceEnum aVideoType,
286 : dom::MediaSourceEnum aAudioType,
287 : bool aFake);
288 : already_AddRefed<PledgeSourceSet>
289 : EnumerateDevicesImpl(uint64_t aWindowId,
290 : dom::MediaSourceEnum aVideoSrcType,
291 : dom::MediaSourceEnum aAudioSrcType,
292 : bool aFake = false);
293 : already_AddRefed<PledgeChar>
294 : SelectSettings(
295 : dom::MediaStreamConstraints& aConstraints,
296 : bool aIsChrome,
297 : RefPtr<media::Refcountable<UniquePtr<SourceSet>>>& aSources);
298 :
299 : void GetPref(nsIPrefBranch *aBranch, const char *aPref,
300 : const char *aData, int32_t *aVal);
301 : void GetPrefBool(nsIPrefBranch *aBranch, const char *aPref,
302 : const char *aData, bool *aVal);
303 : void GetPrefs(nsIPrefBranch *aBranch, const char *aData);
304 :
305 : // Make private because we want only one instance of this class
306 : MediaManager();
307 :
308 0 : ~MediaManager() {}
309 : void Shutdown();
310 :
311 : void StopScreensharing(uint64_t aWindowID);
312 : void IterateWindowListeners(nsPIDOMWindowInner *aWindow,
313 : WindowListenerCallback aCallback,
314 : void *aData);
315 :
316 : void StopMediaStreams();
317 : void RemoveMediaDevicesCallback(uint64_t aWindowID);
318 :
319 : // ONLY access from MainThread so we don't need to lock
320 : WindowTable mActiveWindows;
321 : nsRefPtrHashtable<nsStringHashKey, GetUserMediaTask> mActiveCallbacks;
322 : nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mCallIds;
323 : nsTArray<RefPtr<dom::GetUserMediaRequest>> mPendingGUMRequest;
324 :
325 : // Always exists
326 : nsAutoPtr<base::Thread> mMediaThread;
327 : nsCOMPtr<nsIAsyncShutdownBlocker> mShutdownBlocker;
328 :
329 : // ONLY accessed from MediaManagerThread
330 : RefPtr<MediaEngine> mBackend;
331 :
332 : static StaticRefPtr<MediaManager> sSingleton;
333 :
334 : media::CoatCheck<PledgeSourceSet> mOutstandingPledges;
335 : media::CoatCheck<PledgeChar> mOutstandingCharPledges;
336 : media::CoatCheck<PledgeVoid> mOutstandingVoidPledges;
337 : public:
338 : media::CoatCheck<media::Pledge<nsCString>> mGetPrincipalKeyPledges;
339 : RefPtr<media::Parent<media::NonE10s>> mNonE10sParent;
340 : };
341 :
342 : } // namespace mozilla
343 :
344 : #endif // MOZILLA_MEDIAMANAGER_H
|