2012-06-03 11:35:15 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
2014-10-01 03:17:53 +04:00
|
|
|
#ifndef MOZILLA_MEDIAMANAGER_H
|
|
|
|
#define MOZILLA_MEDIAMANAGER_H
|
|
|
|
|
2012-06-03 11:35:15 +04:00
|
|
|
#include "MediaEngine.h"
|
|
|
|
#include "mozilla/Services.h"
|
2013-01-25 06:45:36 +04:00
|
|
|
#include "mozilla/unused.h"
|
2012-12-22 12:09:36 +04:00
|
|
|
#include "nsIMediaManager.h"
|
2012-06-03 11:35:15 +04:00
|
|
|
|
|
|
|
#include "nsHashKeys.h"
|
2012-07-12 15:53:48 +04:00
|
|
|
#include "nsGlobalWindow.h"
|
2012-06-03 11:35:15 +04:00
|
|
|
#include "nsClassHashtable.h"
|
2012-10-06 04:20:47 +04:00
|
|
|
#include "nsRefPtrHashtable.h"
|
2014-04-14 23:04:27 +04:00
|
|
|
#include "nsIObserver.h"
|
2013-03-05 01:02:17 +04:00
|
|
|
#include "nsIPrefService.h"
|
|
|
|
#include "nsIPrefBranch.h"
|
2012-06-03 11:35:15 +04:00
|
|
|
|
2012-06-11 03:44:50 +04:00
|
|
|
#include "nsPIDOMWindow.h"
|
2012-06-03 11:35:15 +04:00
|
|
|
#include "nsIDOMNavigatorUserMedia.h"
|
2013-01-25 06:45:36 +04:00
|
|
|
#include "nsXULAppAPI.h"
|
2012-06-15 06:31:55 +04:00
|
|
|
#include "mozilla/Attributes.h"
|
2014-02-25 15:50:42 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
2012-12-22 12:09:36 +04:00
|
|
|
#include "mozilla/StaticPtr.h"
|
2014-04-04 13:54:25 +04:00
|
|
|
#include "mozilla/dom/MediaStreamBinding.h"
|
2013-09-16 10:34:57 +04:00
|
|
|
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
2014-10-27 22:42:56 +03:00
|
|
|
#include "mozilla/dom/MediaStreamError.h"
|
2015-06-18 18:46:36 +03:00
|
|
|
#include "mozilla/media/MediaChild.h"
|
|
|
|
#include "mozilla/media/MediaParent.h"
|
2015-05-19 21:15:34 +03:00
|
|
|
#include "mozilla/Logging.h"
|
2013-05-03 09:07:37 +04:00
|
|
|
#include "DOMMediaStream.h"
|
2012-06-03 11:35:15 +04:00
|
|
|
|
2013-01-29 20:55:09 +04:00
|
|
|
#ifdef MOZ_WEBRTC
|
|
|
|
#include "mtransport/runnable_utils.h"
|
|
|
|
#endif
|
|
|
|
|
2014-09-12 18:49:39 +04:00
|
|
|
// Note, these suck in Windows headers, unfortunately.
|
|
|
|
#include "base/thread.h"
|
|
|
|
#include "base/task.h"
|
|
|
|
|
2013-05-02 16:00:12 +04:00
|
|
|
#ifdef MOZ_WIDGET_GONK
|
|
|
|
#include "DOMCameraManager.h"
|
|
|
|
#endif
|
|
|
|
|
2012-06-03 11:35:15 +04:00
|
|
|
namespace mozilla {
|
2013-09-16 10:34:57 +04:00
|
|
|
namespace dom {
|
2014-06-19 04:57:51 +04:00
|
|
|
struct MediaStreamConstraints;
|
2015-09-21 01:45:57 +03:00
|
|
|
struct MediaTrackConstraints;
|
2014-09-24 19:17:33 +04:00
|
|
|
struct MediaTrackConstraintSet;
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace dom
|
2012-06-03 11:35:15 +04:00
|
|
|
|
2012-10-30 03:32:10 +04:00
|
|
|
extern PRLogModuleInfo* GetMediaManagerLog();
|
2015-06-04 01:25:57 +03:00
|
|
|
#define MM_LOG(msg) MOZ_LOG(GetMediaManagerLog(), mozilla::LogLevel::Debug, msg)
|
2012-10-16 00:41:46 +04:00
|
|
|
|
2015-09-19 07:49:07 +03:00
|
|
|
class MediaDevice : public nsIMediaDevice
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
|
|
NS_DECL_NSIMEDIADEVICE
|
|
|
|
|
|
|
|
void SetId(const nsAString& aID);
|
|
|
|
virtual uint32_t GetBestFitnessDistance(
|
|
|
|
const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets);
|
|
|
|
protected:
|
|
|
|
virtual ~MediaDevice() {}
|
|
|
|
explicit MediaDevice(MediaEngineSource* aSource, bool aIsVideo);
|
|
|
|
static uint32_t FitnessDistance(nsString aN,
|
|
|
|
const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aConstraint);
|
|
|
|
private:
|
|
|
|
static bool StringsContain(const dom::OwningStringOrStringSequence& aStrings,
|
|
|
|
nsString aN);
|
|
|
|
static uint32_t FitnessDistance(nsString aN,
|
|
|
|
const dom::ConstrainDOMStringParameters& aParams);
|
|
|
|
protected:
|
|
|
|
nsString mName;
|
|
|
|
nsString mID;
|
|
|
|
dom::MediaSourceEnum mMediaSource;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<MediaEngineSource> mSource;
|
2015-09-19 07:49:07 +03:00
|
|
|
public:
|
|
|
|
dom::MediaSourceEnum GetMediaSource() {
|
|
|
|
return mMediaSource;
|
|
|
|
}
|
|
|
|
bool mIsVideo;
|
|
|
|
};
|
|
|
|
|
|
|
|
class VideoDevice : public MediaDevice
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef MediaEngineVideoSource Source;
|
|
|
|
|
|
|
|
explicit VideoDevice(Source* aSource);
|
|
|
|
NS_IMETHOD GetType(nsAString& aType);
|
|
|
|
Source* GetSource();
|
|
|
|
nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
|
|
|
|
const MediaEnginePrefs &aPrefs);
|
|
|
|
nsresult Restart(const dom::MediaTrackConstraints &aConstraints,
|
|
|
|
const MediaEnginePrefs &aPrefs);
|
|
|
|
};
|
|
|
|
|
|
|
|
class AudioDevice : public MediaDevice
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef MediaEngineAudioSource Source;
|
|
|
|
|
|
|
|
explicit AudioDevice(Source* aSource);
|
|
|
|
NS_IMETHOD GetType(nsAString& aType);
|
|
|
|
Source* GetSource();
|
|
|
|
nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
|
|
|
|
const MediaEnginePrefs &aPrefs);
|
|
|
|
nsresult Restart(const dom::MediaTrackConstraints &aConstraints,
|
|
|
|
const MediaEnginePrefs &aPrefs);
|
|
|
|
};
|
|
|
|
|
2013-01-01 03:12:15 +04:00
|
|
|
/**
|
|
|
|
* This class is an implementation of MediaStreamListener. This is used
|
|
|
|
* to Start() and Stop() the underlying MediaEngineSource when MediaStreams
|
|
|
|
* are assigned and deassigned in content.
|
|
|
|
*/
|
|
|
|
class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener
|
|
|
|
{
|
|
|
|
public:
|
2013-01-07 06:31:32 +04:00
|
|
|
// Create in an inactive state
|
2014-09-12 18:49:39 +04:00
|
|
|
GetUserMediaCallbackMediaStreamListener(base::Thread *aThread,
|
2013-01-07 06:31:32 +04:00
|
|
|
uint64_t aWindowID)
|
2013-01-01 03:12:15 +04:00
|
|
|
: mMediaThread(aThread)
|
2013-01-08 06:44:43 +04:00
|
|
|
, mWindowID(aWindowID)
|
2013-03-03 06:49:29 +04:00
|
|
|
, mStopped(false)
|
2013-03-03 07:04:40 +04:00
|
|
|
, mFinished(false)
|
2015-09-30 09:08:33 +03:00
|
|
|
, mRemoved(false)
|
|
|
|
, mAudioStopped(false)
|
|
|
|
, mVideoStopped(false) {}
|
2013-01-01 03:12:15 +04:00
|
|
|
|
|
|
|
~GetUserMediaCallbackMediaStreamListener()
|
|
|
|
{
|
2015-05-29 21:28:03 +03:00
|
|
|
unused << mMediaThread;
|
2013-01-08 06:44:43 +04:00
|
|
|
// It's OK to release mStream on any thread; they have thread-safe
|
2013-01-04 21:16:32 +04:00
|
|
|
// refcounts.
|
2013-01-01 03:12:15 +04:00
|
|
|
}
|
|
|
|
|
2013-01-07 06:31:32 +04:00
|
|
|
void Activate(already_AddRefed<SourceMediaStream> aStream,
|
2015-09-19 07:49:07 +03:00
|
|
|
AudioDevice* aAudioDevice,
|
|
|
|
VideoDevice* aVideoDevice)
|
2013-01-07 06:31:32 +04:00
|
|
|
{
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2013-03-03 06:49:29 +04:00
|
|
|
mStream = aStream;
|
2015-09-19 07:49:07 +03:00
|
|
|
mAudioDevice = aAudioDevice;
|
|
|
|
mVideoDevice = aVideoDevice;
|
2013-01-07 06:31:32 +04:00
|
|
|
|
|
|
|
mStream->AddListener(this);
|
|
|
|
}
|
|
|
|
|
2013-03-03 06:49:29 +04:00
|
|
|
MediaStream *Stream() // Can be used to test if Activate was called
|
2013-01-04 21:16:32 +04:00
|
|
|
{
|
|
|
|
return mStream;
|
|
|
|
}
|
2013-01-01 03:12:15 +04:00
|
|
|
SourceMediaStream *GetSourceStream()
|
|
|
|
{
|
2013-01-09 07:10:09 +04:00
|
|
|
NS_ASSERTION(mStream,"Getting stream from never-activated GUMCMSListener");
|
|
|
|
if (!mStream) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2013-01-04 21:16:32 +04:00
|
|
|
return mStream->AsSourceStream();
|
2013-01-01 03:12:15 +04:00
|
|
|
}
|
|
|
|
|
2015-07-24 15:28:16 +03:00
|
|
|
void StopSharing();
|
2014-08-22 13:27:16 +04:00
|
|
|
|
2014-08-27 09:03:50 +04:00
|
|
|
void StopTrack(TrackID aID, bool aIsAudio);
|
|
|
|
|
2015-09-20 17:04:51 +03:00
|
|
|
typedef media::Pledge<bool, dom::MediaStreamError*> PledgeVoid;
|
|
|
|
|
|
|
|
already_AddRefed<PledgeVoid>
|
|
|
|
ApplyConstraintsToTrack(nsPIDOMWindow* aWindow,
|
|
|
|
TrackID aID, bool aIsAudio,
|
|
|
|
const dom::MediaTrackConstraints& aConstraints);
|
2015-09-21 01:45:57 +03:00
|
|
|
|
2015-09-19 07:49:07 +03:00
|
|
|
// mVideo/AudioDevice are set by Activate(), so we assume they're capturing
|
2013-07-05 09:53:10 +04:00
|
|
|
// if set and represent a real capture device.
|
2013-02-28 00:36:06 +04:00
|
|
|
bool CapturingVideo()
|
|
|
|
{
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-09-19 07:49:07 +03:00
|
|
|
return mVideoDevice && !mStopped &&
|
2015-09-25 08:55:29 +03:00
|
|
|
!mVideoDevice->GetSource()->IsAvailable() &&
|
2015-09-19 07:49:07 +03:00
|
|
|
mVideoDevice->GetMediaSource() == dom::MediaSourceEnum::Camera &&
|
|
|
|
(!mVideoDevice->GetSource()->IsFake() ||
|
2014-02-25 15:50:42 +04:00
|
|
|
Preferences::GetBool("media.navigator.permission.fake"));
|
2013-02-28 00:36:06 +04:00
|
|
|
}
|
|
|
|
bool CapturingAudio()
|
|
|
|
{
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-09-19 07:49:07 +03:00
|
|
|
return mAudioDevice && !mStopped &&
|
2015-09-25 08:55:29 +03:00
|
|
|
!mAudioDevice->GetSource()->IsAvailable() &&
|
2015-09-19 07:49:07 +03:00
|
|
|
(!mAudioDevice->GetSource()->IsFake() ||
|
2014-02-25 15:50:42 +04:00
|
|
|
Preferences::GetBool("media.navigator.permission.fake"));
|
2013-03-03 06:49:29 +04:00
|
|
|
}
|
2014-07-18 06:23:00 +04:00
|
|
|
bool CapturingScreen()
|
|
|
|
{
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-09-19 07:49:07 +03:00
|
|
|
return mVideoDevice && !mStopped &&
|
|
|
|
!mVideoDevice->GetSource()->IsAvailable() &&
|
|
|
|
mVideoDevice->GetMediaSource() == dom::MediaSourceEnum::Screen;
|
2014-07-18 06:23:00 +04:00
|
|
|
}
|
|
|
|
bool CapturingWindow()
|
|
|
|
{
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-09-19 07:49:07 +03:00
|
|
|
return mVideoDevice && !mStopped &&
|
|
|
|
!mVideoDevice->GetSource()->IsAvailable() &&
|
|
|
|
mVideoDevice->GetMediaSource() == dom::MediaSourceEnum::Window;
|
2014-07-18 06:23:00 +04:00
|
|
|
}
|
2014-08-21 02:05:23 +04:00
|
|
|
bool CapturingApplication()
|
|
|
|
{
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-09-19 07:49:07 +03:00
|
|
|
return mVideoDevice && !mStopped &&
|
|
|
|
!mVideoDevice->GetSource()->IsAvailable() &&
|
|
|
|
mVideoDevice->GetMediaSource() == dom::MediaSourceEnum::Application;
|
2014-08-21 02:05:23 +04:00
|
|
|
}
|
2015-03-11 18:34:31 +03:00
|
|
|
bool CapturingBrowser()
|
|
|
|
{
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-09-19 07:49:07 +03:00
|
|
|
return mVideoDevice && !mStopped &&
|
|
|
|
mVideoDevice->GetSource()->IsAvailable() &&
|
|
|
|
mVideoDevice->GetMediaSource() == dom::MediaSourceEnum::Browser;
|
2015-03-11 18:34:31 +03:00
|
|
|
}
|
2013-03-03 06:49:29 +04:00
|
|
|
|
2014-09-12 18:49:39 +04:00
|
|
|
// implement in .cpp to avoid circular dependency with MediaOperationTask
|
2013-01-08 06:44:43 +04:00
|
|
|
// Can be invoked from EITHER MainThread or MSG thread
|
|
|
|
void Invalidate();
|
2013-01-01 03:12:15 +04:00
|
|
|
|
2013-01-29 20:55:09 +04:00
|
|
|
void
|
|
|
|
AudioConfig(bool aEchoOn, uint32_t aEcho,
|
|
|
|
bool aAgcOn, uint32_t aAGC,
|
2014-04-02 21:58:19 +04:00
|
|
|
bool aNoiseOn, uint32_t aNoise,
|
2014-09-12 18:49:39 +04:00
|
|
|
int32_t aPlayoutDelay);
|
2013-01-29 20:55:09 +04:00
|
|
|
|
2013-01-01 03:12:15 +04:00
|
|
|
void
|
|
|
|
Remove()
|
|
|
|
{
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2013-01-08 06:44:43 +04:00
|
|
|
// allow calling even if inactive (!mStream) for easier cleanup
|
2013-01-01 03:12:15 +04:00
|
|
|
// Caller holds strong reference to us, so no death grip required
|
2013-01-08 06:44:43 +04:00
|
|
|
if (mStream && !mRemoved) {
|
|
|
|
MM_LOG(("Listener removed on purpose, mFinished = %d", (int) mFinished));
|
|
|
|
mRemoved = true; // RemoveListener is async, avoid races
|
2013-01-17 11:38:21 +04:00
|
|
|
// If it's destroyed, don't call - listener will be removed and we'll be notified!
|
|
|
|
if (!mStream->IsDestroyed()) {
|
|
|
|
mStream->RemoveListener(this);
|
|
|
|
}
|
2013-01-08 06:44:43 +04:00
|
|
|
}
|
2013-01-01 03:12:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Proxy NotifyPull() to sources
|
2015-09-30 09:08:22 +03:00
|
|
|
void
|
2015-03-21 19:28:04 +03:00
|
|
|
NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) override
|
2013-01-01 03:12:15 +04:00
|
|
|
{
|
|
|
|
// Currently audio sources ignore NotifyPull, but they could
|
|
|
|
// watch it especially for fake audio.
|
2015-09-19 07:49:07 +03:00
|
|
|
if (mAudioDevice) {
|
|
|
|
mAudioDevice->GetSource()->NotifyPull(aGraph, mStream, kAudioTrack,
|
|
|
|
aDesiredTime);
|
2013-01-01 03:12:15 +04:00
|
|
|
}
|
2015-09-19 07:49:07 +03:00
|
|
|
if (mVideoDevice) {
|
|
|
|
mVideoDevice->GetSource()->NotifyPull(aGraph, mStream, kVideoTrack,
|
|
|
|
aDesiredTime);
|
2013-01-01 03:12:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-30 09:08:22 +03:00
|
|
|
void
|
2014-07-14 09:47:56 +04:00
|
|
|
NotifyEvent(MediaStreamGraph* aGraph,
|
2015-03-21 19:28:04 +03:00
|
|
|
MediaStreamListener::MediaStreamGraphEvent aEvent) override
|
2014-07-14 09:47:56 +04:00
|
|
|
{
|
2014-07-14 09:48:02 +04:00
|
|
|
switch (aEvent) {
|
2014-07-14 09:47:56 +04:00
|
|
|
case EVENT_FINISHED:
|
2015-09-30 09:08:22 +03:00
|
|
|
NS_DispatchToMainThread(
|
|
|
|
NS_NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyFinished));
|
2014-07-14 09:47:56 +04:00
|
|
|
break;
|
|
|
|
case EVENT_REMOVED:
|
2015-09-30 09:08:22 +03:00
|
|
|
NS_DispatchToMainThread(
|
|
|
|
NS_NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyRemoved));
|
2014-07-14 09:47:56 +04:00
|
|
|
break;
|
|
|
|
case EVENT_HAS_DIRECT_LISTENERS:
|
2014-07-14 09:48:02 +04:00
|
|
|
NotifyDirectListeners(aGraph, true);
|
|
|
|
break;
|
2014-07-14 09:47:56 +04:00
|
|
|
case EVENT_HAS_NO_DIRECT_LISTENERS:
|
2014-07-14 09:48:02 +04:00
|
|
|
NotifyDirectListeners(aGraph, false);
|
|
|
|
break;
|
|
|
|
default:
|
2014-07-14 09:47:56 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-30 09:08:22 +03:00
|
|
|
void
|
|
|
|
NotifyFinished();
|
2013-01-08 06:44:43 +04:00
|
|
|
|
2015-09-30 09:08:22 +03:00
|
|
|
void
|
|
|
|
NotifyRemoved();
|
2013-01-01 03:12:15 +04:00
|
|
|
|
2015-09-30 09:08:22 +03:00
|
|
|
void
|
2014-07-14 09:48:02 +04:00
|
|
|
NotifyDirectListeners(MediaStreamGraph* aGraph, bool aHasListeners);
|
|
|
|
|
2013-01-01 03:12:15 +04:00
|
|
|
private:
|
2013-01-08 06:44:43 +04:00
|
|
|
// Set at construction
|
2014-09-12 18:49:39 +04:00
|
|
|
base::Thread* mMediaThread;
|
2013-01-07 06:31:32 +04:00
|
|
|
uint64_t mWindowID;
|
2013-01-08 06:44:43 +04:00
|
|
|
|
2015-09-30 09:08:22 +03:00
|
|
|
// true after this listener has sent MEDIA_STOP. MainThread only.
|
|
|
|
bool mStopped;
|
|
|
|
|
|
|
|
// true after the stream this listener is listening to has finished in the
|
|
|
|
// MediaStreamGraph. MainThread only.
|
|
|
|
bool mFinished;
|
|
|
|
|
|
|
|
// true after this listener has been removed from its MediaStream.
|
|
|
|
// MainThread only.
|
|
|
|
bool mRemoved;
|
2013-03-03 06:49:29 +04:00
|
|
|
|
2015-09-30 09:08:33 +03:00
|
|
|
// true if we have sent MEDIA_STOP or MEDIA_STOP_TRACK for mAudioDevice.
|
|
|
|
// MainThread only.
|
|
|
|
bool mAudioStopped;
|
|
|
|
|
|
|
|
// true if we have sent MEDIA_STOP or MEDIA_STOP_TRACK for mAudioDevice.
|
|
|
|
// MainThread only.
|
|
|
|
bool mVideoStopped;
|
|
|
|
|
2013-01-08 06:44:43 +04:00
|
|
|
// Set at Activate on MainThread
|
|
|
|
|
|
|
|
// Accessed from MediaStreamGraph thread, MediaManager thread, and MainThread
|
|
|
|
// No locking needed as they're only addrefed except on the MediaManager thread
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<AudioDevice> mAudioDevice; // threadsafe refcnt
|
|
|
|
RefPtr<VideoDevice> mVideoDevice; // threadsafe refcnt
|
|
|
|
RefPtr<SourceMediaStream> mStream; // threadsafe refcnt
|
2013-01-01 03:12:15 +04:00
|
|
|
};
|
|
|
|
|
2013-03-03 06:49:29 +04:00
|
|
|
class GetUserMediaNotificationEvent: public nsRunnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum GetUserMediaStatus {
|
|
|
|
STARTING,
|
2014-08-22 13:27:16 +04:00
|
|
|
STOPPING,
|
2015-09-21 01:45:57 +03:00
|
|
|
STOPPED_TRACK,
|
2013-03-03 06:49:29 +04:00
|
|
|
};
|
|
|
|
GetUserMediaNotificationEvent(GetUserMediaCallbackMediaStreamListener* aListener,
|
2013-10-23 15:10:42 +04:00
|
|
|
GetUserMediaStatus aStatus,
|
|
|
|
bool aIsAudio, bool aIsVideo, uint64_t aWindowID)
|
|
|
|
: mListener(aListener) , mStatus(aStatus) , mIsAudio(aIsAudio)
|
|
|
|
, mIsVideo(aIsVideo), mWindowID(aWindowID) {}
|
2013-03-03 06:49:29 +04:00
|
|
|
|
2013-05-03 09:07:37 +04:00
|
|
|
GetUserMediaNotificationEvent(GetUserMediaStatus aStatus,
|
|
|
|
already_AddRefed<DOMMediaStream> aStream,
|
2013-10-23 15:10:42 +04:00
|
|
|
DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback,
|
2013-12-05 18:29:07 +04:00
|
|
|
bool aIsAudio, bool aIsVideo, uint64_t aWindowID,
|
2013-12-06 01:30:50 +04:00
|
|
|
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
|
2013-05-03 09:07:37 +04:00
|
|
|
: mStream(aStream), mOnTracksAvailableCallback(aOnTracksAvailableCallback),
|
2013-12-05 18:29:07 +04:00
|
|
|
mStatus(aStatus), mIsAudio(aIsAudio), mIsVideo(aIsVideo), mWindowID(aWindowID),
|
2014-10-18 04:47:46 +04:00
|
|
|
mOnFailure(aError) {}
|
2013-05-03 09:07:37 +04:00
|
|
|
virtual ~GetUserMediaNotificationEvent()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
2013-03-03 06:49:29 +04:00
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
NS_IMETHOD Run() override;
|
2013-03-03 06:49:29 +04:00
|
|
|
|
|
|
|
protected:
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
|
|
|
|
RefPtr<DOMMediaStream> mStream;
|
2013-05-03 09:07:37 +04:00
|
|
|
nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
|
2013-03-03 06:49:29 +04:00
|
|
|
GetUserMediaStatus mStatus;
|
2013-10-23 15:10:42 +04:00
|
|
|
bool mIsAudio;
|
|
|
|
bool mIsVideo;
|
|
|
|
uint64_t mWindowID;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
2013-03-03 06:49:29 +04:00
|
|
|
};
|
|
|
|
|
2012-10-25 03:21:15 +04:00
|
|
|
typedef enum {
|
|
|
|
MEDIA_START,
|
2014-07-14 09:48:02 +04:00
|
|
|
MEDIA_STOP,
|
2014-08-22 13:27:16 +04:00
|
|
|
MEDIA_STOP_TRACK,
|
2015-09-21 01:45:57 +03:00
|
|
|
MEDIA_DIRECT_LISTENERS,
|
2012-10-25 03:21:15 +04:00
|
|
|
} MediaOperation;
|
|
|
|
|
2013-12-05 18:29:07 +04:00
|
|
|
class MediaManager;
|
2014-09-12 18:49:39 +04:00
|
|
|
class GetUserMediaTask;
|
2013-12-05 18:29:07 +04:00
|
|
|
|
|
|
|
class ReleaseMediaOperationResource : public nsRunnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ReleaseMediaOperationResource(already_AddRefed<DOMMediaStream> aStream,
|
|
|
|
DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback):
|
|
|
|
mStream(aStream),
|
|
|
|
mOnTracksAvailableCallback(aOnTracksAvailableCallback) {}
|
2015-03-21 19:28:04 +03:00
|
|
|
NS_IMETHOD Run() override {return NS_OK;}
|
2013-12-05 18:29:07 +04:00
|
|
|
private:
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DOMMediaStream> mStream;
|
2013-12-05 18:29:07 +04:00
|
|
|
nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
|
|
|
|
};
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
typedef nsTArray<RefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
|
2012-06-03 11:35:15 +04:00
|
|
|
typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable;
|
|
|
|
|
2014-09-20 01:24:28 +04:00
|
|
|
// we could add MediaManager if needed
|
|
|
|
typedef void (*WindowListenerCallback)(MediaManager *aThis,
|
|
|
|
uint64_t aWindowID,
|
|
|
|
StreamListeners *aListeners,
|
|
|
|
void *aData);
|
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
class MediaManager final : public nsIMediaManagerService,
|
2015-03-27 21:52:19 +03:00
|
|
|
public nsIObserver
|
2012-09-20 23:54:00 +04:00
|
|
|
{
|
2015-09-20 17:04:51 +03:00
|
|
|
friend GetUserMediaCallbackMediaStreamListener;
|
2012-06-03 11:35:15 +04:00
|
|
|
public:
|
2012-12-22 12:09:36 +04:00
|
|
|
static already_AddRefed<MediaManager> GetInstance();
|
|
|
|
|
2013-02-14 23:59:27 +04:00
|
|
|
// NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
|
|
|
|
// thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
|
|
|
|
// from MediaManager thread.
|
2013-03-05 01:02:17 +04:00
|
|
|
static MediaManager* Get();
|
2015-03-20 01:43:25 +03:00
|
|
|
static MediaManager* GetIfExists();
|
2015-05-29 21:28:03 +03:00
|
|
|
static void PostTask(const tracked_objects::Location& from_here, Task* task);
|
2015-03-03 17:51:05 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
static bool IsInMediaThread();
|
|
|
|
#endif
|
2013-03-05 01:02:17 +04:00
|
|
|
|
2014-09-06 00:02:54 +04:00
|
|
|
static bool Exists()
|
|
|
|
{
|
|
|
|
return !!sSingleton;
|
|
|
|
}
|
|
|
|
|
2013-11-26 10:22:16 +04:00
|
|
|
static nsresult NotifyRecordingStatusChange(nsPIDOMWindow* aWindow,
|
|
|
|
const nsString& aMsg,
|
|
|
|
const bool& aIsAudio,
|
|
|
|
const bool& aIsVideo);
|
|
|
|
|
2013-07-19 06:21:20 +04:00
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
2012-06-03 11:35:15 +04:00
|
|
|
NS_DECL_NSIOBSERVER
|
2012-12-22 12:09:36 +04:00
|
|
|
NS_DECL_NSIMEDIAMANAGERSERVICE
|
2012-06-03 11:35:15 +04:00
|
|
|
|
2015-06-18 18:46:36 +03:00
|
|
|
media::Parent<media::NonE10s>* GetNonE10sParent();
|
2013-11-06 07:32:42 +04:00
|
|
|
MediaEngine* GetBackend(uint64_t aWindowId = 0);
|
2012-11-14 01:55:02 +04:00
|
|
|
StreamListeners *GetWindowListeners(uint64_t aWindowId) {
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2012-11-14 01:55:02 +04:00
|
|
|
return mActiveWindows.Get(aWindowId);
|
|
|
|
}
|
2014-08-22 14:21:48 +04:00
|
|
|
void RemoveWindowID(uint64_t aWindowId);
|
2012-11-14 01:55:02 +04:00
|
|
|
bool IsWindowStillActive(uint64_t aWindowId) {
|
|
|
|
return !!GetWindowListeners(aWindowId);
|
2012-10-26 04:14:47 +04:00
|
|
|
}
|
2013-01-07 06:31:32 +04:00
|
|
|
// Note: also calls aListener->Remove(), even if inactive
|
|
|
|
void RemoveFromWindowList(uint64_t aWindowID,
|
|
|
|
GetUserMediaCallbackMediaStreamListener *aListener);
|
2012-06-03 11:35:15 +04:00
|
|
|
|
2014-10-01 03:17:53 +04:00
|
|
|
nsresult GetUserMedia(
|
2013-09-16 10:34:57 +04:00
|
|
|
nsPIDOMWindow* aWindow,
|
2014-10-01 03:17:53 +04:00
|
|
|
const dom::MediaStreamConstraints& aConstraints,
|
2012-06-03 11:35:15 +04:00
|
|
|
nsIDOMGetUserMediaSuccessCallback* onSuccess,
|
|
|
|
nsIDOMGetUserMediaErrorCallback* onError);
|
2013-09-16 10:34:57 +04:00
|
|
|
|
2012-09-20 23:54:00 +04:00
|
|
|
nsresult GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
2015-06-18 18:46:36 +03:00
|
|
|
const dom::MediaStreamConstraints& aConstraints,
|
|
|
|
nsIGetUserMediaDevicesSuccessCallback* onSuccess,
|
|
|
|
nsIDOMGetUserMediaErrorCallback* onError,
|
|
|
|
uint64_t aInnerWindowID = 0);
|
2015-03-03 17:51:05 +03:00
|
|
|
|
|
|
|
nsresult EnumerateDevices(nsPIDOMWindow* aWindow,
|
|
|
|
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
|
|
|
nsIDOMGetUserMediaErrorCallback* aOnFailure);
|
|
|
|
|
|
|
|
nsresult EnumerateDevices(nsPIDOMWindow* aWindow, dom::Promise& aPromise);
|
2012-08-22 19:56:38 +04:00
|
|
|
void OnNavigation(uint64_t aWindowID);
|
2015-07-10 06:07:42 +03:00
|
|
|
bool IsActivelyCapturingOrHasAPermission(uint64_t aWindowId);
|
2012-06-03 11:35:15 +04:00
|
|
|
|
2013-03-05 01:02:17 +04:00
|
|
|
MediaEnginePrefs mPrefs;
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
typedef nsTArray<RefPtr<MediaDevice>> SourceSet;
|
2015-07-10 17:15:19 +03:00
|
|
|
static bool IsPrivateBrowsing(nsPIDOMWindow *window);
|
2015-07-03 01:01:52 +03:00
|
|
|
private:
|
2015-09-20 09:26:41 +03:00
|
|
|
typedef media::Pledge<SourceSet*, dom::MediaStreamError*> PledgeSourceSet;
|
2015-10-04 03:42:26 +03:00
|
|
|
typedef media::Pledge<const char*, dom::MediaStreamError*> PledgeChar;
|
2015-06-18 18:46:36 +03:00
|
|
|
|
2015-07-03 01:01:52 +03:00
|
|
|
static bool IsPrivileged();
|
|
|
|
static bool IsLoop(nsIURI* aDocURI);
|
|
|
|
static nsresult GenerateUUID(nsAString& aResult);
|
2015-06-18 18:46:36 +03:00
|
|
|
static nsresult AnonymizeId(nsAString& aId, const nsACString& aOriginKey);
|
|
|
|
public: // TODO: make private once we upgrade to GCC 4.8+ on linux.
|
|
|
|
static void AnonymizeDevices(SourceSet& aDevices, const nsACString& aOriginKey);
|
|
|
|
static already_AddRefed<nsIWritableVariant> ToJSArray(SourceSet& aDevices);
|
|
|
|
private:
|
|
|
|
already_AddRefed<PledgeSourceSet>
|
2015-07-24 15:28:17 +03:00
|
|
|
EnumerateRawDevices(uint64_t aWindowId,
|
|
|
|
dom::MediaSourceEnum aVideoType,
|
|
|
|
dom::MediaSourceEnum aAudioType,
|
2015-07-03 01:01:52 +03:00
|
|
|
bool aFake, bool aFakeTracks);
|
2015-06-18 18:46:36 +03:00
|
|
|
already_AddRefed<PledgeSourceSet>
|
2015-07-24 15:28:17 +03:00
|
|
|
EnumerateDevicesImpl(uint64_t aWindowId,
|
|
|
|
dom::MediaSourceEnum aVideoSrcType,
|
|
|
|
dom::MediaSourceEnum aAudioSrcType,
|
2015-07-03 01:01:52 +03:00
|
|
|
bool aFake = false, bool aFakeTracks = false);
|
2015-10-04 03:42:26 +03:00
|
|
|
already_AddRefed<PledgeChar>
|
|
|
|
SelectSettings(
|
|
|
|
dom::MediaStreamConstraints& aConstraints,
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<media::Refcountable<ScopedDeletePtr<SourceSet>>>& aSources);
|
2015-06-18 18:46:36 +03:00
|
|
|
|
2015-03-03 17:51:05 +03:00
|
|
|
StreamListeners* AddWindowID(uint64_t aWindowId);
|
2012-10-26 04:14:47 +04:00
|
|
|
WindowTable *GetActiveWindows() {
|
2015-09-30 09:08:22 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2012-10-26 04:14:47 +04:00
|
|
|
return &mActiveWindows;
|
2012-12-09 21:23:19 +04:00
|
|
|
}
|
2012-10-26 04:14:47 +04:00
|
|
|
|
2013-03-05 01:02:17 +04:00
|
|
|
void GetPref(nsIPrefBranch *aBranch, const char *aPref,
|
|
|
|
const char *aData, int32_t *aVal);
|
2013-12-06 23:34:40 +04:00
|
|
|
void GetPrefBool(nsIPrefBranch *aBranch, const char *aPref,
|
|
|
|
const char *aData, bool *aVal);
|
2013-03-05 01:02:17 +04:00
|
|
|
void GetPrefs(nsIPrefBranch *aBranch, const char *aData);
|
|
|
|
|
2012-06-03 11:35:15 +04:00
|
|
|
// Make private because we want only one instance of this class
|
2013-03-05 01:02:17 +04:00
|
|
|
MediaManager();
|
2012-06-03 11:35:15 +04:00
|
|
|
|
2014-02-10 00:34:40 +04:00
|
|
|
~MediaManager() {}
|
2012-06-03 11:35:15 +04:00
|
|
|
|
2014-08-22 13:27:16 +04:00
|
|
|
void StopScreensharing(uint64_t aWindowID);
|
2014-09-20 01:24:28 +04:00
|
|
|
void IterateWindowListeners(nsPIDOMWindow *aWindow,
|
|
|
|
WindowListenerCallback aCallback,
|
|
|
|
void *aData);
|
2014-08-22 13:27:16 +04:00
|
|
|
|
2013-09-13 12:51:48 +04:00
|
|
|
void StopMediaStreams();
|
|
|
|
|
2012-10-26 04:14:47 +04:00
|
|
|
// ONLY access from MainThread so we don't need to lock
|
|
|
|
WindowTable mActiveWindows;
|
2014-09-12 18:49:39 +04:00
|
|
|
nsClassHashtable<nsStringHashKey, GetUserMediaTask> mActiveCallbacks;
|
2014-01-09 01:51:33 +04:00
|
|
|
nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mCallIds;
|
2015-02-23 19:50:48 +03:00
|
|
|
|
2012-10-26 04:14:47 +04:00
|
|
|
// Always exists
|
2014-09-12 18:49:39 +04:00
|
|
|
nsAutoPtr<base::Thread> mMediaThread;
|
2012-10-26 04:14:47 +04:00
|
|
|
|
2012-10-25 03:21:15 +04:00
|
|
|
Mutex mMutex;
|
|
|
|
// protected with mMutex:
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<MediaEngine> mBackend;
|
2012-06-03 11:35:15 +04:00
|
|
|
|
2012-12-22 12:09:36 +04:00
|
|
|
static StaticRefPtr<MediaManager> sSingleton;
|
2013-05-02 16:00:12 +04:00
|
|
|
|
2015-06-18 18:46:36 +03:00
|
|
|
media::CoatCheck<PledgeSourceSet> mOutstandingPledges;
|
2015-10-04 03:42:26 +03:00
|
|
|
media::CoatCheck<PledgeChar> mOutstandingCharPledges;
|
2015-09-20 17:04:51 +03:00
|
|
|
media::CoatCheck<GetUserMediaCallbackMediaStreamListener::PledgeVoid> mOutstandingVoidPledges;
|
2015-03-11 02:39:49 +03:00
|
|
|
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsDOMCameraManager> mCameraManager;
|
2013-05-02 16:00:12 +04:00
|
|
|
#endif
|
2015-06-18 18:46:36 +03:00
|
|
|
public:
|
|
|
|
media::CoatCheck<media::Pledge<nsCString>> mGetOriginKeyPledges;
|
|
|
|
ScopedDeletePtr<media::Parent<media::NonE10s>> mNonE10sParent;
|
2012-06-03 11:35:15 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
2014-10-01 03:17:53 +04:00
|
|
|
|
|
|
|
#endif // MOZILLA_MEDIAMANAGER_H
|