Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/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
0
  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
  {
175
    return !!sSingleton;
176
  }
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
0
  WindowTable *GetActiveWindows() {
188
0
    MOZ_ASSERT(NS_IsMainThread());
189
0
    return &mActiveWindows;
190
0
  }
191
  GetUserMediaWindowListener *GetWindowListener(uint64_t aWindowId) {
192
    MOZ_ASSERT(NS_IsMainThread());
193
    return mActiveWindows.GetWeak(aWindowId);
194
  }
195
  void AddWindowID(uint64_t aWindowId, GetUserMediaWindowListener *aListener);
196
  void RemoveWindowID(uint64_t aWindowId);
197
  void SendPendingGUMRequest();
198
  bool IsWindowStillActive(uint64_t aWindowId) {
199
    return !!GetWindowListener(aWindowId);
200
  }
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
0
  ~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