/work/obj-fuzz/dist/include/mozilla/MediaManager.h
Line | Count | Source (jump to first uncovered line) |
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 "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" |
16 | | |
17 | | #include "nsHashKeys.h" |
18 | | #include "nsClassHashtable.h" |
19 | | #include "nsRefPtrHashtable.h" |
20 | | #include "nsIObserver.h" |
21 | | #include "nsIPrefService.h" |
22 | | #include "nsIPrefBranch.h" |
23 | | |
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/dom/NavigatorBinding.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 | | enum class MediaDeviceKind : uint8_t; |
54 | | } // namespace dom |
55 | | |
56 | | namespace ipc { |
57 | | class PrincipalInfo; |
58 | | } |
59 | | |
60 | | class AllocationHandle; |
61 | | class GetUserMediaTask; |
62 | | class GetUserMediaWindowListener; |
63 | | class MediaManager; |
64 | | class SourceListener; |
65 | | |
66 | | LogModule* GetMediaManagerLog(); |
67 | | |
68 | | class MediaDevice : public nsIMediaDevice |
69 | | { |
70 | | public: |
71 | | NS_DECL_THREADSAFE_ISUPPORTS |
72 | | NS_DECL_NSIMEDIADEVICE |
73 | | |
74 | | explicit MediaDevice(MediaEngineSource* aSource, |
75 | | const nsString& aName, |
76 | | const nsString& aID, |
77 | | const nsString& aRawID = NS_LITERAL_STRING("")); |
78 | | |
79 | | explicit MediaDevice(const nsString& aName, |
80 | | const dom::MediaDeviceKind aKind, |
81 | | const nsString& aID, |
82 | | const nsString& aRawID = NS_LITERAL_STRING("")); |
83 | | |
84 | | explicit MediaDevice(const MediaDevice* aOther, |
85 | | const nsString& aID, |
86 | | const nsString& aRawID); |
87 | | |
88 | | uint32_t GetBestFitnessDistance( |
89 | | const nsTArray<const NormalizedConstraintSet*>& aConstraintSets, |
90 | | bool aIsChrome); |
91 | | |
92 | | nsresult Allocate(const dom::MediaTrackConstraints& aConstraints, |
93 | | const MediaEnginePrefs& aPrefs, |
94 | | const mozilla::ipc::PrincipalInfo& aPrincipalInfo, |
95 | | const char** aOutBadConstraint); |
96 | | nsresult SetTrack(const RefPtr<SourceMediaStream>& aStream, |
97 | | TrackID aTrackID, |
98 | | const PrincipalHandle& aPrincipal); |
99 | | nsresult Start(); |
100 | | nsresult Reconfigure(const dom::MediaTrackConstraints& aConstraints, |
101 | | const MediaEnginePrefs& aPrefs, |
102 | | const char** aOutBadConstraint); |
103 | | nsresult FocusOnSelectedSource(); |
104 | | nsresult Stop(); |
105 | | nsresult Deallocate(); |
106 | | |
107 | | void Pull(const RefPtr<SourceMediaStream>& aStream, |
108 | | TrackID aTrackID, |
109 | | StreamTime aDesiredTime, |
110 | | const PrincipalHandle& aPrincipal); |
111 | | |
112 | | void GetSettings(dom::MediaTrackSettings& aOutSettings) const; |
113 | | |
114 | | dom::MediaSourceEnum GetMediaSource() const; |
115 | | protected: |
116 | | virtual ~MediaDevice() = default; |
117 | | |
118 | | static uint32_t FitnessDistance(nsString aN, |
119 | | const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aConstraint); |
120 | | private: |
121 | | static bool StringsContain(const dom::OwningStringOrStringSequence& aStrings, |
122 | | nsString aN); |
123 | | static uint32_t FitnessDistance(nsString aN, |
124 | | const dom::ConstrainDOMStringParameters& aParams); |
125 | | |
126 | | // Assigned on allocation on media thread, then read on the media thread and |
127 | | // graph thread |
128 | | RefPtr<AllocationHandle> mAllocationHandle; |
129 | | |
130 | | public: |
131 | | const RefPtr<MediaEngineSource> mSource; |
132 | | const dom::MediaDeviceKind mKind; |
133 | | const bool mScary; |
134 | | const nsString mType; |
135 | | const nsString mName; |
136 | | const nsString mID; |
137 | | const nsString mRawID; |
138 | | }; |
139 | | |
140 | | typedef nsRefPtrHashtable<nsUint64HashKey, GetUserMediaWindowListener> WindowTable; |
141 | | |
142 | | class MediaManager final : public nsIMediaManagerService, |
143 | | public nsIObserver |
144 | | ,public DeviceChangeCallback |
145 | | { |
146 | | friend SourceListener; |
147 | | public: |
148 | | static already_AddRefed<MediaManager> GetInstance(); |
149 | | |
150 | | // NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager |
151 | | // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread |
152 | | // from MediaManager thread. |
153 | | static MediaManager* Get(); |
154 | | static MediaManager* GetIfExists(); |
155 | | static void StartupInit(); |
156 | | static void PostTask(already_AddRefed<Runnable> task); |
157 | | |
158 | | /** |
159 | | * Posts an async operation to the media manager thread. |
160 | | * FunctionType must be a function that takes a `MozPromiseHolder&`. |
161 | | * |
162 | | * The returned promise is resolved or rejected by aFunction on the media |
163 | | * manager thread. |
164 | | */ |
165 | | template<typename MozPromiseType, typename FunctionType> |
166 | | static RefPtr<MozPromiseType> |
167 | | PostTask(const char* aName, FunctionType&& aFunction); |
168 | | |
169 | | #ifdef DEBUG |
170 | | static bool IsInMediaThread(); |
171 | | #endif |
172 | | |
173 | | static bool Exists() |
174 | 0 | { |
175 | 0 | return !!sSingleton; |
176 | 0 | } |
177 | | |
178 | | static nsresult NotifyRecordingStatusChange(nsPIDOMWindowInner* aWindow); |
179 | | |
180 | | NS_DECL_THREADSAFE_ISUPPORTS |
181 | | NS_DECL_NSIOBSERVER |
182 | | NS_DECL_NSIMEDIAMANAGERSERVICE |
183 | | |
184 | | media::Parent<media::NonE10s>* GetNonE10sParent(); |
185 | | MediaEngine* GetBackend(uint64_t aWindowId = 0); |
186 | | |
187 | | WindowTable *GetActiveWindows() { |
188 | | MOZ_ASSERT(NS_IsMainThread()); |
189 | | return &mActiveWindows; |
190 | | } |
191 | 0 | GetUserMediaWindowListener *GetWindowListener(uint64_t aWindowId) { |
192 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
193 | 0 | return mActiveWindows.GetWeak(aWindowId); |
194 | 0 | } |
195 | | void AddWindowID(uint64_t aWindowId, GetUserMediaWindowListener *aListener); |
196 | | void RemoveWindowID(uint64_t aWindowId); |
197 | | void SendPendingGUMRequest(); |
198 | 0 | bool IsWindowStillActive(uint64_t aWindowId) { |
199 | 0 | return !!GetWindowListener(aWindowId); |
200 | 0 | } |
201 | | bool IsWindowListenerStillActive(GetUserMediaWindowListener* aListener); |
202 | | // Note: also calls aListener->Remove(), even if inactive |
203 | | void RemoveFromWindowList(uint64_t aWindowID, |
204 | | GetUserMediaWindowListener *aListener); |
205 | | |
206 | | typedef dom::CallbackObjectHolder<dom::NavigatorUserMediaSuccessCallback, |
207 | | nsIDOMGetUserMediaSuccessCallback> GetUserMediaSuccessCallback; |
208 | | typedef dom::CallbackObjectHolder<dom::NavigatorUserMediaErrorCallback, |
209 | | nsIDOMGetUserMediaErrorCallback> GetUserMediaErrorCallback; |
210 | | |
211 | | nsresult GetUserMedia( |
212 | | nsPIDOMWindowInner* aWindow, |
213 | | const dom::MediaStreamConstraints& aConstraints, |
214 | | GetUserMediaSuccessCallback&& onSuccess, |
215 | | GetUserMediaErrorCallback&& onError, |
216 | | dom::CallerType aCallerType); |
217 | | |
218 | | nsresult GetUserMediaDevices(nsPIDOMWindowInner* aWindow, |
219 | | const dom::MediaStreamConstraints& aConstraints, |
220 | | dom::MozGetUserMediaDevicesSuccessCallback& aOnSuccess, |
221 | | uint64_t aInnerWindowID = 0, |
222 | | const nsAString& aCallID = nsString()); |
223 | | |
224 | | nsresult EnumerateDevices(nsPIDOMWindowInner* aWindow, |
225 | | nsIGetUserMediaDevicesSuccessCallback* aOnSuccess, |
226 | | nsIDOMGetUserMediaErrorCallback* aOnFailure, |
227 | | dom::CallerType aCallerType); |
228 | | |
229 | | nsresult EnumerateDevices(nsPIDOMWindowInner* aWindow, dom::Promise& aPromise); |
230 | | void OnNavigation(uint64_t aWindowID); |
231 | | bool IsActivelyCapturingOrHasAPermission(uint64_t aWindowId); |
232 | | |
233 | | MediaEnginePrefs mPrefs; |
234 | | |
235 | | typedef nsTArray<RefPtr<MediaDevice>> MediaDeviceSet; |
236 | | |
237 | | virtual int AddDeviceChangeCallback(DeviceChangeCallback* aCallback) override; |
238 | | virtual void OnDeviceChange() override; |
239 | | private: |
240 | | typedef media::Pledge<MediaDeviceSet*, dom::MediaStreamError*> PledgeMediaDeviceSet; |
241 | | typedef media::Pledge<const char*, dom::MediaStreamError*> PledgeChar; |
242 | | typedef media::Pledge<bool, dom::MediaStreamError*> PledgeVoid; |
243 | | |
244 | | static nsresult GenerateUUID(nsAString& aResult); |
245 | | static nsresult AnonymizeId(nsAString& aId, const nsACString& aOriginKey); |
246 | | public: // TODO: make private once we upgrade to GCC 4.8+ on linux. |
247 | | static void AnonymizeDevices(MediaDeviceSet& aDevices, const nsACString& aOriginKey); |
248 | | static already_AddRefed<nsIWritableVariant> ToJSArray(MediaDeviceSet& aDevices); |
249 | | private: |
250 | | enum class DeviceEnumerationType :uint8_t { |
251 | | Normal, // Enumeration should not return loopback or fake devices |
252 | | Fake, // Enumeration should return fake device(s) |
253 | | Loopback /* Enumeration should return loopback device(s) (possibly in |
254 | | addition to normal devices) */ |
255 | | }; |
256 | | already_AddRefed<PledgeMediaDeviceSet> |
257 | | EnumerateRawDevices(uint64_t aWindowId, |
258 | | dom::MediaSourceEnum aVideoInputType, |
259 | | dom::MediaSourceEnum aAudioInputType, |
260 | | MediaSinkEnum aAudioOutputType, |
261 | | DeviceEnumerationType aVideoInputEnumType = DeviceEnumerationType::Normal, |
262 | | DeviceEnumerationType aAudioInputEnumType = DeviceEnumerationType::Normal); |
263 | | already_AddRefed<PledgeMediaDeviceSet> |
264 | | EnumerateDevicesImpl(uint64_t aWindowId, |
265 | | dom::MediaSourceEnum aVideoInputType, |
266 | | dom::MediaSourceEnum aAudioInputType, |
267 | | MediaSinkEnum aAudioOutputType, |
268 | | DeviceEnumerationType aVideoInputEnumType, |
269 | | DeviceEnumerationType aAudioInputEnumType); |
270 | | already_AddRefed<PledgeChar> |
271 | | SelectSettings( |
272 | | dom::MediaStreamConstraints& aConstraints, |
273 | | bool aIsChrome, |
274 | | RefPtr<media::Refcountable<UniquePtr<MediaDeviceSet>>>& aSources); |
275 | | |
276 | | void GetPref(nsIPrefBranch *aBranch, const char *aPref, |
277 | | const char *aData, int32_t *aVal); |
278 | | void GetPrefBool(nsIPrefBranch *aBranch, const char *aPref, |
279 | | const char *aData, bool *aVal); |
280 | | void GetPrefs(nsIPrefBranch *aBranch, const char *aData); |
281 | | |
282 | | // Make private because we want only one instance of this class |
283 | | MediaManager(); |
284 | | |
285 | | ~MediaManager() {} |
286 | | void Shutdown(); |
287 | | |
288 | | void StopScreensharing(uint64_t aWindowID); |
289 | | |
290 | | /** |
291 | | * Calls aCallback with a GetUserMediaWindowListener argument once for |
292 | | * each window listener associated with aWindow and its child windows. |
293 | | */ |
294 | | template<typename FunctionType> |
295 | | void IterateWindowListeners(nsPIDOMWindowInner *aWindow, |
296 | | const FunctionType& aCallback); |
297 | | |
298 | | void StopMediaStreams(); |
299 | | void RemoveMediaDevicesCallback(uint64_t aWindowID); |
300 | | |
301 | | // ONLY access from MainThread so we don't need to lock |
302 | | WindowTable mActiveWindows; |
303 | | nsRefPtrHashtable<nsStringHashKey, GetUserMediaTask> mActiveCallbacks; |
304 | | nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mCallIds; |
305 | | nsTArray<RefPtr<dom::GetUserMediaRequest>> mPendingGUMRequest; |
306 | | |
307 | | // Always exists |
308 | | nsAutoPtr<base::Thread> mMediaThread; |
309 | | nsCOMPtr<nsIAsyncShutdownBlocker> mShutdownBlocker; |
310 | | |
311 | | // ONLY accessed from MediaManagerThread |
312 | | RefPtr<MediaEngine> mBackend; |
313 | | |
314 | | static StaticRefPtr<MediaManager> sSingleton; |
315 | | |
316 | | media::CoatCheck<PledgeMediaDeviceSet> mOutstandingPledges; |
317 | | media::CoatCheck<PledgeChar> mOutstandingCharPledges; |
318 | | nsTArray<nsString> mDeviceIDs; |
319 | | public: |
320 | | media::CoatCheck<media::Pledge<nsCString>> mGetPrincipalKeyPledges; |
321 | | RefPtr<media::Parent<media::NonE10s>> mNonE10sParent; |
322 | | }; |
323 | | |
324 | | } // namespace mozilla |
325 | | |
326 | | #endif // MOZILLA_MEDIAMANAGER_H |