1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/media/MediaManager.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,580 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "MediaEngine.h" 1.9 +#include "mozilla/Services.h" 1.10 +#include "mozilla/unused.h" 1.11 +#include "nsIMediaManager.h" 1.12 + 1.13 +#include "nsHashKeys.h" 1.14 +#include "nsGlobalWindow.h" 1.15 +#include "nsClassHashtable.h" 1.16 +#include "nsRefPtrHashtable.h" 1.17 +#include "nsIObserver.h" 1.18 +#include "nsIPrefService.h" 1.19 +#include "nsIPrefBranch.h" 1.20 + 1.21 +#include "nsPIDOMWindow.h" 1.22 +#include "nsIDOMNavigatorUserMedia.h" 1.23 +#include "nsXULAppAPI.h" 1.24 +#include "mozilla/Attributes.h" 1.25 +#include "mozilla/Preferences.h" 1.26 +#include "mozilla/StaticPtr.h" 1.27 +#include "mozilla/dom/MediaStreamBinding.h" 1.28 +#include "mozilla/dom/MediaStreamTrackBinding.h" 1.29 +#include "prlog.h" 1.30 +#include "DOMMediaStream.h" 1.31 + 1.32 +#ifdef MOZ_WEBRTC 1.33 +#include "mtransport/runnable_utils.h" 1.34 +#endif 1.35 + 1.36 +#ifdef MOZ_WIDGET_GONK 1.37 +#include "DOMCameraManager.h" 1.38 +#endif 1.39 + 1.40 +namespace mozilla { 1.41 +namespace dom { 1.42 +class MediaStreamConstraints; 1.43 +class NavigatorUserMediaSuccessCallback; 1.44 +class NavigatorUserMediaErrorCallback; 1.45 +} 1.46 + 1.47 +#ifdef PR_LOGGING 1.48 +extern PRLogModuleInfo* GetMediaManagerLog(); 1.49 +#define MM_LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg) 1.50 +#else 1.51 +#define MM_LOG(msg) 1.52 +#endif 1.53 + 1.54 +/** 1.55 + * This class is an implementation of MediaStreamListener. This is used 1.56 + * to Start() and Stop() the underlying MediaEngineSource when MediaStreams 1.57 + * are assigned and deassigned in content. 1.58 + */ 1.59 +class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener 1.60 +{ 1.61 +public: 1.62 + // Create in an inactive state 1.63 + GetUserMediaCallbackMediaStreamListener(nsIThread *aThread, 1.64 + uint64_t aWindowID) 1.65 + : mMediaThread(aThread) 1.66 + , mWindowID(aWindowID) 1.67 + , mStopped(false) 1.68 + , mFinished(false) 1.69 + , mLock("mozilla::GUMCMSL") 1.70 + , mRemoved(false) {} 1.71 + 1.72 + ~GetUserMediaCallbackMediaStreamListener() 1.73 + { 1.74 + // It's OK to release mStream on any thread; they have thread-safe 1.75 + // refcounts. 1.76 + } 1.77 + 1.78 + void Activate(already_AddRefed<SourceMediaStream> aStream, 1.79 + MediaEngineSource* aAudioSource, 1.80 + MediaEngineSource* aVideoSource) 1.81 + { 1.82 + NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); 1.83 + mStream = aStream; 1.84 + mAudioSource = aAudioSource; 1.85 + mVideoSource = aVideoSource; 1.86 + mLastEndTimeAudio = 0; 1.87 + mLastEndTimeVideo = 0; 1.88 + 1.89 + mStream->AddListener(this); 1.90 + } 1.91 + 1.92 + MediaStream *Stream() // Can be used to test if Activate was called 1.93 + { 1.94 + return mStream; 1.95 + } 1.96 + SourceMediaStream *GetSourceStream() 1.97 + { 1.98 + NS_ASSERTION(mStream,"Getting stream from never-activated GUMCMSListener"); 1.99 + if (!mStream) { 1.100 + return nullptr; 1.101 + } 1.102 + return mStream->AsSourceStream(); 1.103 + } 1.104 + 1.105 + // mVideo/AudioSource are set by Activate(), so we assume they're capturing 1.106 + // if set and represent a real capture device. 1.107 + bool CapturingVideo() 1.108 + { 1.109 + NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); 1.110 + return mVideoSource && !mStopped && 1.111 + (!mVideoSource->IsFake() || 1.112 + Preferences::GetBool("media.navigator.permission.fake")); 1.113 + } 1.114 + bool CapturingAudio() 1.115 + { 1.116 + NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); 1.117 + return mAudioSource && !mStopped && 1.118 + (!mAudioSource->IsFake() || 1.119 + Preferences::GetBool("media.navigator.permission.fake")); 1.120 + } 1.121 + 1.122 + void SetStopped() 1.123 + { 1.124 + mStopped = true; 1.125 + } 1.126 + 1.127 + // implement in .cpp to avoid circular dependency with MediaOperationRunnable 1.128 + // Can be invoked from EITHER MainThread or MSG thread 1.129 + void Invalidate(); 1.130 + 1.131 + void 1.132 + AudioConfig(bool aEchoOn, uint32_t aEcho, 1.133 + bool aAgcOn, uint32_t aAGC, 1.134 + bool aNoiseOn, uint32_t aNoise, 1.135 + int32_t aPlayoutDelay) 1.136 + { 1.137 + if (mAudioSource) { 1.138 +#ifdef MOZ_WEBRTC 1.139 + // Right now these configs are only of use if webrtc is available 1.140 + RUN_ON_THREAD(mMediaThread, 1.141 + WrapRunnable(nsRefPtr<MediaEngineSource>(mAudioSource), // threadsafe 1.142 + &MediaEngineSource::Config, 1.143 + aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn, aNoise, aPlayoutDelay), 1.144 + NS_DISPATCH_NORMAL); 1.145 +#endif 1.146 + } 1.147 + } 1.148 + 1.149 + void 1.150 + Remove() 1.151 + { 1.152 + NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); 1.153 + // allow calling even if inactive (!mStream) for easier cleanup 1.154 + // Caller holds strong reference to us, so no death grip required 1.155 + MutexAutoLock lock(mLock); // protect access to mRemoved 1.156 + if (mStream && !mRemoved) { 1.157 + MM_LOG(("Listener removed on purpose, mFinished = %d", (int) mFinished)); 1.158 + mRemoved = true; // RemoveListener is async, avoid races 1.159 + // If it's destroyed, don't call - listener will be removed and we'll be notified! 1.160 + if (!mStream->IsDestroyed()) { 1.161 + mStream->RemoveListener(this); 1.162 + } 1.163 + } 1.164 + } 1.165 + 1.166 + // Proxy NotifyPull() to sources 1.167 + virtual void 1.168 + NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) MOZ_OVERRIDE 1.169 + { 1.170 + // Currently audio sources ignore NotifyPull, but they could 1.171 + // watch it especially for fake audio. 1.172 + if (mAudioSource) { 1.173 + mAudioSource->NotifyPull(aGraph, mStream, kAudioTrack, aDesiredTime, mLastEndTimeAudio); 1.174 + } 1.175 + if (mVideoSource) { 1.176 + mVideoSource->NotifyPull(aGraph, mStream, kVideoTrack, aDesiredTime, mLastEndTimeVideo); 1.177 + } 1.178 + } 1.179 + 1.180 + virtual void 1.181 + NotifyFinished(MediaStreamGraph* aGraph) MOZ_OVERRIDE; 1.182 + 1.183 + virtual void 1.184 + NotifyRemoved(MediaStreamGraph* aGraph) MOZ_OVERRIDE; 1.185 + 1.186 +private: 1.187 + // Set at construction 1.188 + nsCOMPtr<nsIThread> mMediaThread; 1.189 + uint64_t mWindowID; 1.190 + 1.191 + bool mStopped; // MainThread only 1.192 + 1.193 + // Set at Activate on MainThread 1.194 + 1.195 + // Accessed from MediaStreamGraph thread, MediaManager thread, and MainThread 1.196 + // No locking needed as they're only addrefed except on the MediaManager thread 1.197 + nsRefPtr<MediaEngineSource> mAudioSource; // threadsafe refcnt 1.198 + nsRefPtr<MediaEngineSource> mVideoSource; // threadsafe refcnt 1.199 + nsRefPtr<SourceMediaStream> mStream; // threadsafe refcnt 1.200 + TrackTicks mLastEndTimeAudio; 1.201 + TrackTicks mLastEndTimeVideo; 1.202 + bool mFinished; 1.203 + 1.204 + // Accessed from MainThread and MSG thread 1.205 + Mutex mLock; // protects mRemoved access from MainThread 1.206 + bool mRemoved; 1.207 +}; 1.208 + 1.209 +class GetUserMediaNotificationEvent: public nsRunnable 1.210 +{ 1.211 + public: 1.212 + enum GetUserMediaStatus { 1.213 + STARTING, 1.214 + STOPPING 1.215 + }; 1.216 + GetUserMediaNotificationEvent(GetUserMediaCallbackMediaStreamListener* aListener, 1.217 + GetUserMediaStatus aStatus, 1.218 + bool aIsAudio, bool aIsVideo, uint64_t aWindowID) 1.219 + : mListener(aListener) , mStatus(aStatus) , mIsAudio(aIsAudio) 1.220 + , mIsVideo(aIsVideo), mWindowID(aWindowID) {} 1.221 + 1.222 + GetUserMediaNotificationEvent(GetUserMediaStatus aStatus, 1.223 + already_AddRefed<DOMMediaStream> aStream, 1.224 + DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback, 1.225 + bool aIsAudio, bool aIsVideo, uint64_t aWindowID, 1.226 + already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError) 1.227 + : mStream(aStream), mOnTracksAvailableCallback(aOnTracksAvailableCallback), 1.228 + mStatus(aStatus), mIsAudio(aIsAudio), mIsVideo(aIsVideo), mWindowID(aWindowID), 1.229 + mError(aError) {} 1.230 + virtual ~GetUserMediaNotificationEvent() 1.231 + { 1.232 + 1.233 + } 1.234 + 1.235 + NS_IMETHOD Run() MOZ_OVERRIDE; 1.236 + 1.237 + protected: 1.238 + nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe 1.239 + nsRefPtr<DOMMediaStream> mStream; 1.240 + nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback; 1.241 + GetUserMediaStatus mStatus; 1.242 + bool mIsAudio; 1.243 + bool mIsVideo; 1.244 + uint64_t mWindowID; 1.245 + nsRefPtr<nsIDOMGetUserMediaErrorCallback> mError; 1.246 +}; 1.247 + 1.248 +typedef enum { 1.249 + MEDIA_START, 1.250 + MEDIA_STOP 1.251 +} MediaOperation; 1.252 + 1.253 +class MediaManager; 1.254 +class GetUserMediaRunnable; 1.255 + 1.256 +/** 1.257 + * Send an error back to content. The error is the form a string. 1.258 + * Do this only on the main thread. The success callback is also passed here 1.259 + * so it can be released correctly. 1.260 + */ 1.261 +class ErrorCallbackRunnable : public nsRunnable 1.262 +{ 1.263 +public: 1.264 + ErrorCallbackRunnable( 1.265 + nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess, 1.266 + nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError, 1.267 + const nsAString& aErrorMsg, uint64_t aWindowID); 1.268 + NS_IMETHOD Run(); 1.269 +private: 1.270 + ~ErrorCallbackRunnable(); 1.271 + 1.272 + nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess; 1.273 + nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError; 1.274 + const nsString mErrorMsg; 1.275 + uint64_t mWindowID; 1.276 + nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable 1.277 +}; 1.278 + 1.279 +class ReleaseMediaOperationResource : public nsRunnable 1.280 +{ 1.281 +public: 1.282 + ReleaseMediaOperationResource(already_AddRefed<DOMMediaStream> aStream, 1.283 + DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback): 1.284 + mStream(aStream), 1.285 + mOnTracksAvailableCallback(aOnTracksAvailableCallback) {} 1.286 + NS_IMETHOD Run() MOZ_OVERRIDE {return NS_OK;} 1.287 +private: 1.288 + nsRefPtr<DOMMediaStream> mStream; 1.289 + nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback; 1.290 +}; 1.291 + 1.292 +// Generic class for running long media operations like Start off the main 1.293 +// thread, and then (because nsDOMMediaStreams aren't threadsafe), 1.294 +// ProxyReleases mStream since it's cycle collected. 1.295 +class MediaOperationRunnable : public nsRunnable 1.296 +{ 1.297 +public: 1.298 + // so we can send Stop without AddRef()ing from the MSG thread 1.299 + MediaOperationRunnable(MediaOperation aType, 1.300 + GetUserMediaCallbackMediaStreamListener* aListener, 1.301 + DOMMediaStream* aStream, 1.302 + DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback, 1.303 + MediaEngineSource* aAudioSource, 1.304 + MediaEngineSource* aVideoSource, 1.305 + bool aNeedsFinish, 1.306 + uint64_t aWindowID, 1.307 + already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError) 1.308 + : mType(aType) 1.309 + , mStream(aStream) 1.310 + , mOnTracksAvailableCallback(aOnTracksAvailableCallback) 1.311 + , mAudioSource(aAudioSource) 1.312 + , mVideoSource(aVideoSource) 1.313 + , mListener(aListener) 1.314 + , mFinish(aNeedsFinish) 1.315 + , mWindowID(aWindowID) 1.316 + , mError(aError) 1.317 + {} 1.318 + 1.319 + ~MediaOperationRunnable() 1.320 + { 1.321 + // MediaStreams can be released on any thread. 1.322 + } 1.323 + 1.324 + nsresult returnAndCallbackError(nsresult rv, const char* errorLog) 1.325 + { 1.326 + MM_LOG(("%s , rv=%d", errorLog, rv)); 1.327 + NS_DispatchToMainThread(new ReleaseMediaOperationResource(mStream.forget(), 1.328 + mOnTracksAvailableCallback.forget())); 1.329 + nsString log; 1.330 + 1.331 + log.AssignASCII(errorLog, strlen(errorLog)); 1.332 + nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success; 1.333 + NS_DispatchToMainThread(new ErrorCallbackRunnable(success, mError, 1.334 + log, mWindowID)); 1.335 + return NS_OK; 1.336 + } 1.337 + 1.338 + NS_IMETHOD 1.339 + Run() MOZ_OVERRIDE 1.340 + { 1.341 + SourceMediaStream *source = mListener->GetSourceStream(); 1.342 + // No locking between these is required as all the callbacks for the 1.343 + // same MediaStream will occur on the same thread. 1.344 + if (!source) // means the stream was never Activated() 1.345 + return NS_OK; 1.346 + 1.347 + switch (mType) { 1.348 + case MEDIA_START: 1.349 + { 1.350 + NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread"); 1.351 + nsresult rv; 1.352 + 1.353 + source->SetPullEnabled(true); 1.354 + 1.355 + DOMMediaStream::TrackTypeHints expectedTracks = 0; 1.356 + if (mAudioSource) { 1.357 + rv = mAudioSource->Start(source, kAudioTrack); 1.358 + if (NS_SUCCEEDED(rv)) { 1.359 + expectedTracks |= DOMMediaStream::HINT_CONTENTS_AUDIO; 1.360 + } else { 1.361 + return returnAndCallbackError(rv, "Starting audio failed"); 1.362 + } 1.363 + } 1.364 + if (mVideoSource) { 1.365 + rv = mVideoSource->Start(source, kVideoTrack); 1.366 + if (NS_SUCCEEDED(rv)) { 1.367 + expectedTracks |= DOMMediaStream::HINT_CONTENTS_VIDEO; 1.368 + } else { 1.369 + return returnAndCallbackError(rv, "Starting video failed"); 1.370 + } 1.371 + } 1.372 + 1.373 + mOnTracksAvailableCallback->SetExpectedTracks(expectedTracks); 1.374 + 1.375 + MM_LOG(("started all sources")); 1.376 + // Forward mOnTracksAvailableCallback to GetUserMediaNotificationEvent, 1.377 + // because mOnTracksAvailableCallback needs to be added to mStream 1.378 + // on the main thread. 1.379 + nsIRunnable *event = 1.380 + new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING, 1.381 + mStream.forget(), 1.382 + mOnTracksAvailableCallback.forget(), 1.383 + mAudioSource != nullptr, 1.384 + mVideoSource != nullptr, 1.385 + mWindowID, mError.forget()); 1.386 + // event must always be released on mainthread due to the JS callbacks 1.387 + // in the TracksAvailableCallback 1.388 + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); 1.389 + } 1.390 + break; 1.391 + 1.392 + case MEDIA_STOP: 1.393 + { 1.394 + NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread"); 1.395 + if (mAudioSource) { 1.396 + mAudioSource->Stop(source, kAudioTrack); 1.397 + mAudioSource->Deallocate(); 1.398 + } 1.399 + if (mVideoSource) { 1.400 + mVideoSource->Stop(source, kVideoTrack); 1.401 + mVideoSource->Deallocate(); 1.402 + } 1.403 + // Do this after stopping all tracks with EndTrack() 1.404 + if (mFinish) { 1.405 + source->Finish(); 1.406 + } 1.407 + nsIRunnable *event = 1.408 + new GetUserMediaNotificationEvent(mListener, 1.409 + GetUserMediaNotificationEvent::STOPPING, 1.410 + mAudioSource != nullptr, 1.411 + mVideoSource != nullptr, 1.412 + mWindowID); 1.413 + // event must always be released on mainthread due to the JS callbacks 1.414 + // in the TracksAvailableCallback 1.415 + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); 1.416 + } 1.417 + break; 1.418 + 1.419 + default: 1.420 + MOZ_ASSERT(false,"invalid MediaManager operation"); 1.421 + break; 1.422 + } 1.423 + return NS_OK; 1.424 + } 1.425 + 1.426 +private: 1.427 + MediaOperation mType; 1.428 + nsRefPtr<DOMMediaStream> mStream; 1.429 + nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback; 1.430 + nsRefPtr<MediaEngineSource> mAudioSource; // threadsafe 1.431 + nsRefPtr<MediaEngineSource> mVideoSource; // threadsafe 1.432 + nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe 1.433 + bool mFinish; 1.434 + uint64_t mWindowID; 1.435 + nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError; 1.436 +}; 1.437 + 1.438 +typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners; 1.439 +typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable; 1.440 + 1.441 +class MediaDevice : public nsIMediaDevice 1.442 +{ 1.443 +public: 1.444 + NS_DECL_THREADSAFE_ISUPPORTS 1.445 + NS_DECL_NSIMEDIADEVICE 1.446 + 1.447 + static MediaDevice* Create(MediaEngineVideoSource* source); 1.448 + static MediaDevice* Create(MediaEngineAudioSource* source); 1.449 + 1.450 + virtual ~MediaDevice() {} 1.451 +protected: 1.452 + MediaDevice(MediaEngineSource* aSource); 1.453 + nsString mName; 1.454 + nsString mID; 1.455 + bool mHasFacingMode; 1.456 + dom::VideoFacingModeEnum mFacingMode; 1.457 + nsRefPtr<MediaEngineSource> mSource; 1.458 +}; 1.459 + 1.460 +class VideoDevice : public MediaDevice 1.461 +{ 1.462 +public: 1.463 + VideoDevice(MediaEngineVideoSource* aSource); 1.464 + NS_IMETHOD GetType(nsAString& aType); 1.465 + MediaEngineVideoSource* GetSource(); 1.466 +}; 1.467 + 1.468 +class AudioDevice : public MediaDevice 1.469 +{ 1.470 +public: 1.471 + AudioDevice(MediaEngineAudioSource* aSource); 1.472 + NS_IMETHOD GetType(nsAString& aType); 1.473 + MediaEngineAudioSource* GetSource(); 1.474 +}; 1.475 + 1.476 +// we could add MediaManager if needed 1.477 +typedef void (*WindowListenerCallback)(MediaManager *aThis, 1.478 + uint64_t aWindowID, 1.479 + StreamListeners *aListeners, 1.480 + void *aData); 1.481 + 1.482 +class MediaManager MOZ_FINAL : public nsIMediaManagerService, 1.483 + public nsIObserver 1.484 +{ 1.485 +public: 1.486 + static already_AddRefed<MediaManager> GetInstance(); 1.487 + 1.488 + // NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager 1.489 + // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread 1.490 + // from MediaManager thread. 1.491 + static MediaManager* Get(); 1.492 + 1.493 + static bool Exists() 1.494 + { 1.495 + return !!sSingleton; 1.496 + } 1.497 + 1.498 + static nsIThread* GetThread() { 1.499 + return Get()->mMediaThread; 1.500 + } 1.501 + 1.502 + static nsresult NotifyRecordingStatusChange(nsPIDOMWindow* aWindow, 1.503 + const nsString& aMsg, 1.504 + const bool& aIsAudio, 1.505 + const bool& aIsVideo); 1.506 + 1.507 + NS_DECL_THREADSAFE_ISUPPORTS 1.508 + NS_DECL_NSIOBSERVER 1.509 + NS_DECL_NSIMEDIAMANAGERSERVICE 1.510 + 1.511 + MediaEngine* GetBackend(uint64_t aWindowId = 0); 1.512 + StreamListeners *GetWindowListeners(uint64_t aWindowId) { 1.513 + NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread"); 1.514 + 1.515 + return mActiveWindows.Get(aWindowId); 1.516 + } 1.517 + void RemoveWindowID(uint64_t aWindowId) { 1.518 + mActiveWindows.Remove(aWindowId); 1.519 + } 1.520 + bool IsWindowStillActive(uint64_t aWindowId) { 1.521 + return !!GetWindowListeners(aWindowId); 1.522 + } 1.523 + // Note: also calls aListener->Remove(), even if inactive 1.524 + void RemoveFromWindowList(uint64_t aWindowID, 1.525 + GetUserMediaCallbackMediaStreamListener *aListener); 1.526 + 1.527 + nsresult GetUserMedia(bool aPrivileged, 1.528 + nsPIDOMWindow* aWindow, 1.529 + const dom::MediaStreamConstraints& aRawConstraints, 1.530 + nsIDOMGetUserMediaSuccessCallback* onSuccess, 1.531 + nsIDOMGetUserMediaErrorCallback* onError); 1.532 + 1.533 + nsresult GetUserMediaDevices(nsPIDOMWindow* aWindow, 1.534 + const dom::MediaStreamConstraints& aConstraints, 1.535 + nsIGetUserMediaDevicesSuccessCallback* onSuccess, 1.536 + nsIDOMGetUserMediaErrorCallback* onError, 1.537 + uint64_t aInnerWindowID = 0); 1.538 + void OnNavigation(uint64_t aWindowID); 1.539 + 1.540 + MediaEnginePrefs mPrefs; 1.541 + 1.542 +private: 1.543 + WindowTable *GetActiveWindows() { 1.544 + NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread"); 1.545 + return &mActiveWindows; 1.546 + } 1.547 + 1.548 + void GetPref(nsIPrefBranch *aBranch, const char *aPref, 1.549 + const char *aData, int32_t *aVal); 1.550 + void GetPrefBool(nsIPrefBranch *aBranch, const char *aPref, 1.551 + const char *aData, bool *aVal); 1.552 + void GetPrefs(nsIPrefBranch *aBranch, const char *aData); 1.553 + 1.554 + // Make private because we want only one instance of this class 1.555 + MediaManager(); 1.556 + 1.557 + ~MediaManager() {} 1.558 + 1.559 + void IterateWindowListeners(nsPIDOMWindow *aWindow, 1.560 + WindowListenerCallback aCallback, 1.561 + void *aData); 1.562 + 1.563 + void StopMediaStreams(); 1.564 + 1.565 + // ONLY access from MainThread so we don't need to lock 1.566 + WindowTable mActiveWindows; 1.567 + nsRefPtrHashtable<nsStringHashKey, GetUserMediaRunnable> mActiveCallbacks; 1.568 + nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mCallIds; 1.569 + // Always exists 1.570 + nsCOMPtr<nsIThread> mMediaThread; 1.571 + 1.572 + Mutex mMutex; 1.573 + // protected with mMutex: 1.574 + RefPtr<MediaEngine> mBackend; 1.575 + 1.576 + static StaticRefPtr<MediaManager> sSingleton; 1.577 + 1.578 +#ifdef MOZ_B2G_CAMERA 1.579 + nsRefPtr<nsDOMCameraManager> mCameraManager; 1.580 +#endif 1.581 +}; 1.582 + 1.583 +} // namespace mozilla