--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1205,16 +1205,23 @@ public:
return NS_OK;
}
private:
nsAutoPtr<GetUserMediaTask> mTask;
};
#endif
+// TODO: Remove once upgraded to GCC 4.8+ on linux. Bogus error on static func:
+// error: 'this' was not captured for this lambda function
+
+static auto& MediaManager_GetInstance = MediaManager::GetInstance;
+static auto& MediaManager_ToJSArray = MediaManager::ToJSArray;
+static auto& MediaManager_AnonymizeDevices = MediaManager::AnonymizeDevices;
+
/**
* EnumerateRawDevices - Enumerate a list of audio & video devices that
* satisfy passed-in constraints. List contains raw id's.
*/
already_AddRefed<MediaManager::PledgeSourceSet>
MediaManager::EnumerateRawDevices(uint64_t aWindowId,
const MediaStreamConstraints& aConstraints)
@@ -1231,17 +1238,17 @@ MediaManager::EnumerateRawDevices(uint64
MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, aConstraints, aWindowId,
audioLoopDev, videoLoopDev,
fake]() mutable {
nsRefPtr<MediaEngine> backend;
if (aConstraints.mFake || fake) {
backend = new MediaEngineDefault(aConstraints.mFakeTracks);
} else {
- nsRefPtr<MediaManager> manager = MediaManager::GetInstance();
+ nsRefPtr<MediaManager> manager = MediaManager_GetInstance();
backend = manager->GetBackend(aWindowId);
}
ScopedDeletePtr<SourceSet> result(new SourceSet);
if (IsOn(aConstraints.mVideo)) {
nsTArray<nsRefPtr<VideoDevice>> sources;
GetSources(backend, GetInvariant(aConstraints.mVideo),
&MediaEngine::EnumerateVideoDevices, sources, videoLoopDev);
@@ -1255,17 +1262,17 @@ MediaManager::EnumerateRawDevices(uint64
&MediaEngine::EnumerateAudioDevices, sources, audioLoopDev);
for (auto& source : sources) {
result->AppendElement(source);
}
}
SourceSet* handoff = result.forget();
NS_DispatchToMainThread(NewRunnableFrom([id, handoff]() mutable {
ScopedDeletePtr<SourceSet> result(handoff);
- auto* mgr = MediaManager::GetIfExists();
+ nsRefPtr<MediaManager> mgr = MediaManager_GetInstance();
if (!mgr) {
return NS_OK;
}
nsRefPtr<PledgeSourceSet> p = mgr->mOutstandingPledges.Remove(id);
if (p) {
p->Resolve(result.forget());
}
return NS_OK;
@@ -1363,16 +1370,25 @@ MediaManager::GetIfExists() {
/* static */ already_AddRefed<MediaManager>
MediaManager::GetInstance()
{
// so we can have non-refcounted getters
nsRefPtr<MediaManager> service = MediaManager::Get();
return service.forget();
}
+media::Parent<media::NonE10s>*
+MediaManager::GetNonE10sParent()
+{
+ if (!mNonE10sParent) {
+ mNonE10sParent = new media::Parent<media::NonE10s>(true);
+ }
+ return mNonE10sParent;
+}
+
/* static */
void
MediaManager::PostTask(const tracked_objects::Location& from_here, Task* task)
{
if (sInShutdown) {
// Can't safely delete task here since it may have items with specific
// thread-release requirements.
return;
@@ -1776,17 +1792,16 @@ MediaManager::ToJSArray(SourceSet& aDevi
return var.forget();
}
already_AddRefed<MediaManager::PledgeSourceSet>
MediaManager::EnumerateDevicesImpl(uint64_t aWindowId,
const MediaStreamConstraints& aConstraints)
{
MOZ_ASSERT(NS_IsMainThread());
- nsRefPtr<MediaManager> that = this; // hold on to this
// This function returns a pledge, a promise-like object with the future result
nsRefPtr<PledgeSourceSet> pledge = new PledgeSourceSet();
uint32_t id = mOutstandingPledges.Append(*pledge);
// To get a device list anonymized for a particular origin, we must:
// 1. Get an origin-key (for either regular or private browsing)
// 2. Get the raw devices list
@@ -1804,34 +1819,34 @@ MediaManager::EnumerateDevicesImpl(uint6
privateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
}
// GetOriginKey is an async API that returns a pledge (a promise-like
// pattern). We use .Then() to pass in a lambda to run back on this same
// thread later once GetOriginKey resolves. Needed variables are "captured"
// (passed by value) safely into the lambda.
nsRefPtr<Pledge<nsCString>> p = media::GetOriginKey(origin, privateBrowsing);
- p->Then([this, that, id, aWindowId,
- aConstraints](const nsCString& aOriginKey) mutable {
+ p->Then([id, aWindowId, aConstraints](const nsCString& aOriginKey) mutable {
MOZ_ASSERT(NS_IsMainThread());
+ nsRefPtr<MediaManager> mgr = MediaManager_GetInstance();
- nsRefPtr<PledgeSourceSet> p = EnumerateRawDevices(aWindowId, aConstraints);
+ nsRefPtr<PledgeSourceSet> p = mgr->EnumerateRawDevices(aWindowId, aConstraints);
p->Then([id, aWindowId, aOriginKey](SourceSet*& aDevices) mutable {
ScopedDeletePtr<SourceSet> devices(aDevices); // secondary result
// Only run if window is still on our active list.
- auto* mgr = MediaManager::GetIfExists();
+ nsRefPtr<MediaManager> mgr = MediaManager_GetInstance();
if (!mgr) {
return NS_OK;
}
nsRefPtr<PledgeSourceSet> p = mgr->mOutstandingPledges.Remove(id);
if (!p || !mgr->IsWindowStillActive(aWindowId)) {
return NS_OK;
}
- AnonymizeDevices(*devices, aOriginKey);
+ MediaManager_AnonymizeDevices(*devices, aOriginKey);
p->Resolve(devices.forget());
return NS_OK;
});
});
return pledge.forget();
}
nsresult
@@ -1849,17 +1864,17 @@ MediaManager::EnumerateDevices(nsPIDOMWi
MediaStreamConstraints c;
c.mVideo.SetAsBoolean() = true;
c.mAudio.SetAsBoolean() = true;
nsRefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(windowId, c);
p->Then([onSuccess](SourceSet*& aDevices) mutable {
ScopedDeletePtr<SourceSet> devices(aDevices); // grab result
- nsCOMPtr<nsIWritableVariant> array = ToJSArray(*devices);
+ nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*devices);
onSuccess->OnSuccess(array);
}, [onFailure](MediaStreamError& reason) mutable {
onFailure->OnError(&reason);
});
return NS_OK;
}
/*
@@ -1878,22 +1893,22 @@ MediaManager::GetUserMediaDevices(nsPIDO
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
if (!aWindowId) {
aWindowId = aWindow->WindowID();
}
nsRefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(aWindowId, aConstraints);
p->Then([aWindowId, onSuccess, onFailure](SourceSet*& aDevices) mutable {
ScopedDeletePtr<SourceSet> devices(aDevices); // grab result
-
+
if (devices->Length()) {
- nsCOMPtr<nsIWritableVariant> array = ToJSArray(*devices);
+ nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*devices);
onSuccess->OnSuccess(array);
} else {
- nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(aWindowId);
+ nsRefPtr<nsGlobalWindow> window = nsGlobalWindow::GetInnerWindowWithId(aWindowId);
if (!window) {
return NS_ERROR_UNEXPECTED;
}
nsRefPtr<MediaStreamError> reason =
new MediaStreamError(window, NS_LITERAL_STRING("NotFoundError"));
onFailure->OnError(reason);
}
return NS_OK;
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -23,16 +23,17 @@
#include "nsXULAppAPI.h"
#include "mozilla/Attributes.h"
#include "mozilla/Preferences.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/MediaStreamTrackBinding.h"
#include "mozilla/dom/MediaStreamError.h"
#include "mozilla/media/MediaChild.h"
+#include "mozilla/media/MediaParent.h"
#include "mozilla/Logging.h"
#include "DOMMediaStream.h"
#ifdef MOZ_WEBRTC
#include "mtransport/runnable_utils.h"
#endif
// Note, these suck in Windows headers, unfortunately.
@@ -528,16 +529,17 @@ public:
const nsString& aMsg,
const bool& aIsAudio,
const bool& aIsVideo);
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIMEDIAMANAGERSERVICE
+ media::Parent<media::NonE10s>* GetNonE10sParent();
MediaEngine* GetBackend(uint64_t aWindowId = 0);
StreamListeners *GetWindowListeners(uint64_t aWindowId) {
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
return mActiveWindows.Get(aWindowId);
}
void RemoveWindowID(uint64_t aWindowId);
bool IsWindowStillActive(uint64_t aWindowId) {
@@ -568,20 +570,21 @@ public:
bool IsWindowActivelyCapturing(uint64_t aWindowId);
MediaEnginePrefs mPrefs;
private:
typedef nsTArray<nsRefPtr<MediaDevice>> SourceSet;
typedef media::Pledge<SourceSet*, dom::MediaStreamError> PledgeSourceSet;
+ 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 nsresult AnonymizeId(nsAString& aId, const nsACString& aOriginKey);
static already_AddRefed<nsIWritableVariant> ToJSArray(SourceSet& aDevices);
-
+private:
already_AddRefed<PledgeSourceSet>
EnumerateRawDevices(uint64_t aWindowId,
const dom::MediaStreamConstraints& aConstraints);
already_AddRefed<PledgeSourceSet>
EnumerateDevicesImpl(uint64_t aWindowId,
const dom::MediaStreamConstraints& aConstraints);
StreamListeners* AddWindowID(uint64_t aWindowId);
@@ -623,13 +626,14 @@ private:
static StaticRefPtr<MediaManager> sSingleton;
media::CoatCheck<PledgeSourceSet> mOutstandingPledges;
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
nsRefPtr<nsDOMCameraManager> mCameraManager;
#endif
public:
media::CoatCheck<media::Pledge<nsCString>> mGetOriginKeyPledges;
+ ScopedDeletePtr<media::Parent<media::NonE10s>> mNonE10sParent;
};
} // namespace mozilla
#endif // MOZILLA_MEDIAMANAGER_H
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -999,16 +999,17 @@ RTCPeerConnection.prototype = {
dict.maxRetransmits = dict.maxRetransmitNum;
this.logWarning("Deprecated RTCDataChannelInit dictionary entry maxRetransmitNum used!", null, 0);
}
if (dict.outOfOrderAllowed != undefined) {
dict.ordered = !dict.outOfOrderAllowed; // the meaning is swapped with
// the name change
this.logWarning("Deprecated RTCDataChannelInit dictionary entry outOfOrderAllowed used!", null, 0);
}
+
if (dict.preset != undefined) {
dict.negotiated = dict.preset;
this.logWarning("Deprecated RTCDataChannelInit dictionary entry preset used!", null, 0);
}
if (dict.stream != undefined) {
dict.id = dict.stream;
this.logWarning("Deprecated RTCDataChannelInit dictionary entry stream used!", null, 0);
}
--- a/dom/media/systemservices/MediaChild.cpp
+++ b/dom/media/systemservices/MediaChild.cpp
@@ -17,49 +17,51 @@ PRLogModuleInfo *gMediaChildLog;
#define LOG(args) MOZ_LOG(gMediaChildLog, mozilla::LogLevel::Debug, args)
namespace mozilla {
namespace media {
already_AddRefed<Pledge<nsCString>>
GetOriginKey(const nsCString& aOrigin, bool aPrivateBrowsing)
{
- auto* mgr = MediaManager::GetIfExists();
+ nsRefPtr<MediaManager> mgr = MediaManager::GetInstance();
MOZ_ASSERT(mgr);
nsRefPtr<Pledge<nsCString>> p = new Pledge<nsCString>();
uint32_t id = mgr->mGetOriginKeyPledges.Append(*p);
- if (XRE_GetProcessType() != GeckoProcessType_Default) {
- Child::Get()->SendGetOriginKey(id, aOrigin, aPrivateBrowsing);
+ if (XRE_GetProcessType() == GeckoProcessType_Default) {
+ mgr->GetNonE10sParent()->RecvGetOriginKey(id, aOrigin, aPrivateBrowsing);
} else {
- nsRefPtr<Parent> parent = new Parent(true);
- parent->RecvGetOriginKey(id, aOrigin, aPrivateBrowsing);
+ Child::Get()->SendGetOriginKey(id, aOrigin, aPrivateBrowsing);
}
return p.forget();
}
void
SanitizeOriginKeys(const uint64_t& aSinceWhen)
{
LOG(("SanitizeOriginKeys since %llu", aSinceWhen));
- if (XRE_GetProcessType() != GeckoProcessType_Default) {
- Child::Get()->SendSanitizeOriginKeys(aSinceWhen);
+ if (XRE_GetProcessType() == GeckoProcessType_Default) {
+ // Avoid opening MediaManager in this case, since this is called by
+ // sanitize.js when cookies are cleared, which can happen on startup.
+ ScopedDeletePtr<Parent<NonE10s>> tmpParent(new Parent<NonE10s>(true));
+ tmpParent->RecvSanitizeOriginKeys(aSinceWhen);
} else {
- nsRefPtr<Parent> parent = new Parent(true);
- parent->RecvSanitizeOriginKeys(aSinceWhen);
+ Child::Get()->SendSanitizeOriginKeys(aSinceWhen);
}
}
static Child* sChild;
Child* Child::Get()
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
+ MOZ_ASSERT(NS_IsMainThread());
if (!sChild) {
sChild = static_cast<Child*>(dom::ContentChild::GetSingleton()->SendPMediaConstructor());
}
return sChild;
}
Child::Child()
: mActorDestroyed(false)
@@ -81,36 +83,34 @@ Child::~Child()
void Child::ActorDestroy(ActorDestroyReason aWhy)
{
mActorDestroyed = true;
}
bool
Child::RecvGetOriginKeyResponse(const uint32_t& aRequestId, const nsCString& aKey)
{
- auto* mgr = MediaManager::GetIfExists();
+ nsRefPtr<MediaManager> mgr = MediaManager::GetInstance();
if (!mgr) {
return false;
}
nsRefPtr<Pledge<nsCString>> pledge = mgr->mGetOriginKeyPledges.Remove(aRequestId);
if (pledge) {
pledge->Resolve(aKey);
}
return true;
}
PMediaChild*
AllocPMediaChild()
{
- Child* obj = new Child();
- obj->AddRef();
- return obj;
+ return new Child();
}
bool
DeallocPMediaChild(media::PMediaChild *aActor)
{
- static_cast<Child*>(aActor)->Release();
+ delete static_cast<Child*>(aActor);
return true;
}
}
}
--- a/dom/media/systemservices/MediaChild.h
+++ b/dom/media/systemservices/MediaChild.h
@@ -19,37 +19,34 @@ namespace media {
// functions, for the moment just:
//
// GetOriginKey() - get a cookie-like persisted unique key for a given origin.
// SanitizeOriginKeys() - reset persisted unique keys.
// GetOriginKey and SanitizeOriginKeys are asynchronous APIs that return pledges
// (promise-like objects) with the future value. Use pledge.Then(func) to access.
-class Child;
-
already_AddRefed<Pledge<nsCString>>
GetOriginKey(const nsCString& aOrigin, bool aPrivateBrowsing);
void
SanitizeOriginKeys(const uint64_t& aSinceWhen);
class Child : public PMediaChild
{
- NS_INLINE_DECL_REFCOUNTING(Child)
public:
static Child* Get();
Child();
bool RecvGetOriginKeyResponse(const uint32_t& aRequestId, const nsCString& aKey);
void ActorDestroy(ActorDestroyReason aWhy) override;
+ virtual ~Child();
private:
- virtual ~Child();
bool mActorDestroyed;
};
PMediaChild* AllocPMediaChild();
bool DeallocPMediaChild(PMediaChild *aActor);
} // namespace media
--- a/dom/media/systemservices/MediaParent.cpp
+++ b/dom/media/systemservices/MediaParent.cpp
@@ -27,23 +27,23 @@ PRLogModuleInfo *gMediaParentLog;
// deviceIds to be unique per origin, to avoid them being supercookies.
#define ORIGINKEYS_FILE "enumerate_devices.txt"
#define ORIGINKEYS_VERSION "1"
namespace mozilla {
namespace media {
-static StaticMutex gMutex;
-static ParentSingleton* sParentSingleton = nullptr;
+static Parent<PMediaParent>* sIPCServingParent;
-class ParentSingleton : public nsISupports
+static OriginKeyStore* sOriginKeyStore = nullptr;
+
+class OriginKeyStore : public nsISupports
{
NS_DECL_THREADSAFE_ISUPPORTS
-
class OriginKey
{
public:
static const size_t DecodedLength = 18;
static const size_t EncodedLength = DecodedLength * 4 / 3;
OriginKey(const nsACString& aKey, int64_t aSecondsStamp)
: mKey(aKey)
@@ -319,89 +319,110 @@ class ParentSingleton : public nsISuppor
Load();
}
}
private:
nsCOMPtr<nsIFile> mProfileDir;
};
private:
- virtual ~ParentSingleton()
+ virtual ~OriginKeyStore()
{
- sParentSingleton = nullptr;
+ sOriginKeyStore = nullptr;
LOG((__FUNCTION__));
}
public:
- static ParentSingleton* Get()
+ static OriginKeyStore* Get()
{
- // Protect creation of singleton and access from multiple Background threads.
- //
- // Multiple Background threads happen because sanitize.js calls us from the
- // chrome process and gets a thread separate from the one servicing ipc from
- // the content process.
-
- StaticMutexAutoLock lock(gMutex);
- if (!sParentSingleton) {
- sParentSingleton = new ParentSingleton();
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!sOriginKeyStore) {
+ sOriginKeyStore = new OriginKeyStore();
}
- return sParentSingleton;
+ return sOriginKeyStore;
}
// Only accessed on StreamTS thread
OriginKeysLoader mOriginKeys;
OriginKeysTable mPrivateBrowsingOriginKeys;
-
- // Only accessed on return thread
- CoatCheck<Pledge<nsCString>> mOutstandingPledges;
};
-NS_IMPL_ISUPPORTS0(ParentSingleton)
+NS_IMPL_ISUPPORTS0(OriginKeyStore)
+
+template<> /* static */
+Parent<PMediaParent>* Parent<PMediaParent>::GetSingleton()
+{
+ return sIPCServingParent;
+}
-bool
-Parent::RecvGetOriginKey(const uint32_t& aRequestId,
+template<> /* static */
+Parent<NonE10s>* Parent<NonE10s>::GetSingleton()
+{
+ nsRefPtr<MediaManager> mgr = MediaManager::GetInstance();
+ if (!mgr) {
+ return nullptr;
+ }
+ return mgr->GetNonE10sParent();
+}
+
+// TODO: Remove once upgraded to GCC 4.8+ on linux. Bogus error on static func:
+// error: 'this' was not captured for this lambda function
+
+template<class Super> static
+Parent<Super>* GccGetSingleton() { return Parent<Super>::GetSingleton(); };
+
+
+template<class Super> bool
+Parent<Super>::RecvGetOriginKey(const uint32_t& aRequestId,
const nsCString& aOrigin,
const bool& aPrivateBrowsing)
{
MOZ_ASSERT(NS_IsMainThread());
- nsRefPtr<ParentSingleton> singleton(mSingleton);
// First, get profile dir.
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIFile> profileDir;
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(profileDir));
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
// Then over to stream-transport thread to do the actual file io.
// Stash a pledge to hold the answer and get an id for this request.
+
nsRefPtr<Pledge<nsCString>> p = new Pledge<nsCString>();
- uint32_t id = singleton->mOutstandingPledges.Append(*p);
+ uint32_t id = mOutstandingPledges.Append(*p);
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
MOZ_ASSERT(sts);
- rv = sts->Dispatch(NewRunnableFrom([id, profileDir, singleton,
+ nsRefPtr<OriginKeyStore> store(mOriginKeyStore);
+ bool sameProcess = mSameProcess;
+
+ rv = sts->Dispatch(NewRunnableFrom([id, profileDir, store, sameProcess,
aOrigin, aPrivateBrowsing]() -> nsresult {
MOZ_ASSERT(!NS_IsMainThread());
- singleton->mOriginKeys.SetProfileDir(profileDir);
+ store->mOriginKeys.SetProfileDir(profileDir);
nsCString result;
if (aPrivateBrowsing) {
- singleton->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, result);
+ store->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, result);
} else {
- singleton->mOriginKeys.GetOriginKey(aOrigin, result);
+ store->mOriginKeys.GetOriginKey(aOrigin, result);
}
// Pass result back to main thread.
nsresult rv;
- rv = NS_DispatchToMainThread(NewRunnableFrom([id, singleton,
+ rv = NS_DispatchToMainThread(NewRunnableFrom([id, store, sameProcess,
result]() -> nsresult {
- nsRefPtr<Pledge<nsCString>> p = singleton->mOutstandingPledges.Remove(id);
+ Parent* parent = GccGetSingleton<Super>(); // GetSingleton();
+ if (!parent) {
+ return NS_OK;
+ }
+ nsRefPtr<Pledge<nsCString>> p = parent->mOutstandingPledges.Remove(id);
if (!p) {
return NS_ERROR_UNEXPECTED;
}
p->Resolve(result);
return NS_OK;
}), NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -409,103 +430,109 @@ Parent::RecvGetOriginKey(const uint32_t&
}
return NS_OK;
}), NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
- nsRefPtr<media::Parent> that(this);
- p->Then([this, that, aRequestId](const nsCString& aKey) mutable {
- if (!mDestroyed) {
- if (!mSameProcess) {
- unused << SendGetOriginKeyResponse(aRequestId, aKey);
- } else {
- auto* mgr = MediaManager::GetIfExists();
- if (!mgr) {
- return NS_OK;
- }
- nsRefPtr<Pledge<nsCString>> pledge =
- mgr->mGetOriginKeyPledges.Remove(aRequestId);
- if (pledge) {
- pledge->Resolve(aKey);
- }
+ p->Then([aRequestId, sameProcess](const nsCString& aKey) mutable {
+ if (!sameProcess) {
+ if (!sIPCServingParent) {
+ return NS_OK;
+ }
+ unused << sIPCServingParent->SendGetOriginKeyResponse(aRequestId, aKey);
+ } else {
+ nsRefPtr<MediaManager> mgr = MediaManager::GetInstance();
+ if (!mgr) {
+ return NS_OK;
+ }
+ nsRefPtr<Pledge<nsCString>> pledge =
+ mgr->mGetOriginKeyPledges.Remove(aRequestId);
+ if (pledge) {
+ pledge->Resolve(aKey);
}
}
return NS_OK;
});
return true;
}
-bool
-Parent::RecvSanitizeOriginKeys(const uint64_t& aSinceWhen)
+template<class Super> bool
+Parent<Super>::RecvSanitizeOriginKeys(const uint64_t& aSinceWhen)
{
- nsRefPtr<ParentSingleton> singleton(mSingleton);
-
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIFile> profileDir;
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(profileDir));
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
// Over to stream-transport thread to do the file io.
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
MOZ_ASSERT(sts);
- rv = sts->Dispatch(NewRunnableFrom([profileDir, singleton, aSinceWhen]() -> nsresult {
+ nsRefPtr<OriginKeyStore> store(mOriginKeyStore);
+
+ rv = sts->Dispatch(NewRunnableFrom([profileDir, store, aSinceWhen]() -> nsresult {
MOZ_ASSERT(!NS_IsMainThread());
- singleton->mOriginKeys.SetProfileDir(profileDir);
- singleton->mPrivateBrowsingOriginKeys.Clear(aSinceWhen);
- singleton->mOriginKeys.Clear(aSinceWhen);
+ store->mOriginKeys.SetProfileDir(profileDir);
+ store->mPrivateBrowsingOriginKeys.Clear(aSinceWhen);
+ store->mOriginKeys.Clear(aSinceWhen);
return NS_OK;
}), NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
return true;
}
-void
-Parent::ActorDestroy(ActorDestroyReason aWhy)
+template<class Super> void
+Parent<Super>::ActorDestroy(ActorDestroyReason aWhy)
{
// No more IPC from here
mDestroyed = true;
LOG((__FUNCTION__));
}
-Parent::Parent(bool aSameProcess)
- : mSingleton(ParentSingleton::Get())
+template<class Super>
+Parent<Super>::Parent(bool aSameProcess)
+ : mOriginKeyStore(OriginKeyStore::Get())
, mDestroyed(false)
, mSameProcess(aSameProcess)
{
if (!gMediaParentLog)
gMediaParentLog = PR_NewLogModule("MediaParent");
LOG(("media::Parent: %p", this));
MOZ_COUNT_CTOR(Parent);
}
-Parent::~Parent()
+template<class Super>
+Parent<Super>::~Parent()
{
LOG(("~media::Parent: %p", this));
MOZ_COUNT_DTOR(Parent);
}
PMediaParent*
AllocPMediaParent()
{
- Parent* obj = new Parent();
- obj->AddRef();
- return obj;
+ MOZ_ASSERT(!sIPCServingParent);
+ sIPCServingParent = new Parent<PMediaParent>();
+ return sIPCServingParent;
}
bool
DeallocPMediaParent(media::PMediaParent *aActor)
{
- static_cast<Parent*>(aActor)->Release();
+ MOZ_ASSERT(sIPCServingParent == static_cast<Parent<PMediaParent>*>(aActor));
+ delete sIPCServingParent;
return true;
}
}
}
+
+// Instantiate templates to satisfy linker
+template class mozilla::media::Parent<mozilla::media::NonE10s>;
--- a/dom/media/systemservices/MediaParent.h
+++ b/dom/media/systemservices/MediaParent.h
@@ -11,36 +11,58 @@
#include "mozilla/dom/ContentParent.h"
#include "mozilla/media/PMediaParent.h"
namespace mozilla {
namespace media {
// media::Parent implements the chrome-process side of ipc for media::Child APIs
+// A "SameProcess" version may also be created to service non-e10s calls.
-class ParentSingleton;
+class OriginKeyStore;
-class Parent : public PMediaParent
+class NonE10s
{
- NS_INLINE_DECL_REFCOUNTING(Parent)
+ typedef mozilla::ipc::IProtocolManager<mozilla::ipc::IProtocol>::ActorDestroyReason
+ ActorDestroyReason;
+protected:
+ virtual bool RecvGetOriginKey(const uint32_t& aRequestId,
+ const nsCString& aOrigin,
+ const bool& aPrivateBrowsing) = 0;
+ virtual bool RecvSanitizeOriginKeys(const uint64_t& aSinceWhen) = 0;
+ virtual void
+ ActorDestroy(ActorDestroyReason aWhy) = 0;
+};
+
+// Super = PMediaParent or NonE10s
+
+template<class Super>
+class Parent : public Super
+{
+ typedef mozilla::ipc::IProtocolManager<mozilla::ipc::IProtocol>::ActorDestroyReason
+ ActorDestroyReason;
public:
+ static Parent* GetSingleton();
+
virtual bool RecvGetOriginKey(const uint32_t& aRequestId,
const nsCString& aOrigin,
const bool& aPrivateBrowsing) override;
virtual bool RecvSanitizeOriginKeys(const uint64_t& aSinceWhen) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
- Parent(bool aSameProcess = false);
-private:
+ explicit Parent(bool aSameProcess = false);
virtual ~Parent();
+private:
- nsRefPtr<ParentSingleton> mSingleton;
+ nsRefPtr<OriginKeyStore> mOriginKeyStore;
bool mDestroyed;
bool mSameProcess;
+
+ CoatCheck<Pledge<nsCString>> mOutstandingPledges;
};
PMediaParent* AllocPMediaParent();
bool DeallocPMediaParent(PMediaParent *aActor);
} // namespace media
} // namespace mozilla
--- a/dom/media/systemservices/MediaUtils.h
+++ b/dom/media/systemservices/MediaUtils.h
@@ -35,62 +35,71 @@ namespace media {
* nsRefPtr<media::Pledge<Foo>> p = GetFooAsynchronously(); // returns a pledge
* p->Then([](const Foo& foo) {
* // use foo here (same thread. Need not be thread-safe!)
* });
*
* See media::CoatCheck below for an example of GetFooAsynchronously().
*/
+class PledgeBase
+{
+public:
+ NS_INLINE_DECL_REFCOUNTING(PledgeBase);
+protected:
+ virtual ~PledgeBase() {};
+};
+
template<typename ValueType, typename ErrorType = nsresult>
-class Pledge
+class Pledge : public PledgeBase
{
// TODO: Remove workaround once mozilla allows std::function from <functional>
// wo/std::function support, do template + virtual trick to accept lambdas
class FunctorsBase
{
public:
FunctorsBase() {}
virtual void Succeed(ValueType& result) = 0;
virtual void Fail(ErrorType& error) = 0;
virtual ~FunctorsBase() {};
};
public:
- NS_INLINE_DECL_REFCOUNTING(Pledge);
explicit Pledge() : mDone(false), mError(nullptr) {}
+ Pledge(const Pledge& aOther) = delete;
+ Pledge& operator = (const Pledge&) = delete;
template<typename OnSuccessType>
void Then(OnSuccessType aOnSuccess)
{
Then(aOnSuccess, [](ErrorType&){});
}
template<typename OnSuccessType, typename OnFailureType>
void Then(OnSuccessType aOnSuccess, OnFailureType aOnFailure)
{
- class F : public FunctorsBase
+ class Functors : public FunctorsBase
{
public:
- F(OnSuccessType& aOnSuccess, OnFailureType& aOnFailure)
+ Functors(OnSuccessType& aOnSuccess, OnFailureType& aOnFailure)
: mOnSuccess(aOnSuccess), mOnFailure(aOnFailure) {}
void Succeed(ValueType& result)
{
mOnSuccess(result);
}
void Fail(ErrorType& error)
{
mOnFailure(error);
};
OnSuccessType mOnSuccess;
OnFailureType mOnFailure;
};
- mFunctors = new F(aOnSuccess, aOnFailure);
+ mFunctors = new Functors(aOnSuccess, aOnFailure);
if (mDone) {
if (!mError) {
mFunctors->Succeed(mValue);
} else {
mFunctors->Fail(*mError);
}
}
@@ -120,70 +129,70 @@ protected:
mError = rv;
if (mFunctors) {
mFunctors->Fail(mError);
}
}
}
ValueType mValue;
-protected:
+private:
~Pledge() {};
bool mDone;
nsRefPtr<ErrorType> mError;
-private:
- nsAutoPtr<FunctorsBase> mFunctors;
+ ScopedDeletePtr<FunctorsBase> mFunctors;
};
template<typename ValueType>
-class Pledge<ValueType, nsresult>
+class Pledge<ValueType, nsresult> : public PledgeBase
{
// TODO: Remove workaround once mozilla allows std::function from <functional>
// wo/std::function support, do template + virtual trick to accept lambdas
class FunctorsBase
{
public:
FunctorsBase() {}
virtual void Succeed(ValueType& result) = 0;
virtual void Fail(nsresult error) = 0;
virtual ~FunctorsBase() {};
};
public:
- NS_INLINE_DECL_REFCOUNTING(Pledge);
explicit Pledge() : mDone(false), mError(NS_OK) {}
+ Pledge(const Pledge& aOther) = delete;
+ Pledge& operator = (const Pledge&) = delete;
template<typename OnSuccessType>
void Then(OnSuccessType aOnSuccess)
{
Then(aOnSuccess, [](nsresult){});
}
template<typename OnSuccessType, typename OnFailureType>
void Then(OnSuccessType aOnSuccess, OnFailureType aOnFailure)
{
- class F : public FunctorsBase
+ class Functors : public FunctorsBase
{
public:
- F(OnSuccessType& aOnSuccess, OnFailureType& aOnFailure)
+ Functors(OnSuccessType& aOnSuccess, OnFailureType& aOnFailure)
: mOnSuccess(aOnSuccess), mOnFailure(aOnFailure) {}
void Succeed(ValueType& result)
{
mOnSuccess(result);
}
void Fail(nsresult rv)
{
mOnFailure(rv);
};
OnSuccessType mOnSuccess;
OnFailureType mOnFailure;
};
- mFunctors = new F(aOnSuccess, aOnFailure);
+ mFunctors = new Functors(aOnSuccess, aOnFailure);
if (mDone) {
if (mError == NS_OK) {
mFunctors->Succeed(mValue);
} else {
mFunctors->Fail(mError);
}
}
@@ -213,22 +222,21 @@ protected:
mError = error;
if (mFunctors) {
mFunctors->Fail(mError);
}
}
}
ValueType mValue;
-protected:
+private:
~Pledge() {};
bool mDone;
nsresult mError;
-private:
- nsAutoPtr<FunctorsBase> mFunctors;
+ ScopedDeletePtr<FunctorsBase> mFunctors;
};
/* media::NewRunnableFrom() - Create an nsRunnable from a lambda.
* media::NewTaskFrom() - Create a Task from a lambda.
*
* Passing variables (closures) to an async function is clunky with nsRunnable:
*
* void Foo()
--- a/dom/media/tests/mochitest/test_getUserMedia_constraints.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_constraints.html
@@ -18,24 +18,16 @@ var tests = [
{ message: "unknown required constraint on video ignored",
constraints: { video: { somethingUnknown: { exact: 0 } },
fake: true },
error: null },
{ message: "unknown required constraint on audio ignored",
constraints: { audio: { somethingUnknown: { exact: 0 } },
fake: true },
error: null },
- { message: "video overconstrained by facingMode fails",
- constraints: { video: { facingMode:{ exact: 'left' } },
- fake: true },
- error: "NotFoundError" },
- { message: "video overconstrained by facingMode array fails",
- constraints: { video: { facingMode:{ exact: ['left', 'right'] } },
- fake: true },
- error: "NotFoundError" },
{ message: "audio overconstrained by facingMode ignored",
constraints: { audio: { facingMode: { exact: 'left' } },
fake: true },
error: null },
{ message: "full screensharing requires permission",
constraints: { video: { mediaSource: 'screen' } },
error: "PermissionDeniedError" },
{ message: "application screensharing requires permission",
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
@@ -376,17 +376,17 @@ MediaEngineCameraVideoSource::ChooseCapa
return true;
}
void
MediaEngineCameraVideoSource::SetName(nsString aName)
{
mDeviceName = aName;
bool hasFacingMode = false;
- VideoFacingModeEnum facingMode;
+ VideoFacingModeEnum facingMode = VideoFacingModeEnum::User;
// Set facing mode based on device name.
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
if (aName.EqualsLiteral("back")) {
hasFacingMode = true;
facingMode = VideoFacingModeEnum::Environment;
} else if (aName.EqualsLiteral("front")) {
hasFacingMode = true;
--- a/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
@@ -332,18 +332,18 @@ MediaEngineGonkVideoSource::Stop(SourceM
* constructor and destructor respectively.
*/
void
MediaEngineGonkVideoSource::Init()
{
nsAutoCString deviceName;
ICameraControl::GetCameraName(mCaptureIndex, deviceName);
- CopyUTF8toUTF16(deviceName, mDeviceName);
- CopyUTF8toUTF16(deviceName, mUniqueId);
+ SetName(NS_ConvertUTF8toUTF16(deviceName));
+ SetUUID(deviceName.get());
mInitDone = true;
}
void
MediaEngineGonkVideoSource::Shutdown()
{
LOG((__FUNCTION__));