mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 805451: Remove lock (mostly) and ensure other singleton refs are MainThread r=derf
This commit is contained in:
parent
e289cb5b07
commit
b993796c62
@ -62,13 +62,12 @@ public:
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success(mSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
|
||||
|
||||
{
|
||||
MutexAutoLock lock(MediaManager::Get()->GetMutex());
|
||||
WindowTable* activeWindows = MediaManager::Get()->GetActiveWindows();
|
||||
if (activeWindows->Get(mWindowID)) {
|
||||
error->OnError(mErrorMsg);
|
||||
}
|
||||
if (!(MediaManager::Get()->IsWindowStillActive(mWindowID))) {
|
||||
return NS_OK;
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
error->OnError(mErrorMsg);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -106,14 +105,12 @@ public:
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success(mSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
|
||||
|
||||
{
|
||||
MutexAutoLock lock(MediaManager::Get()->GetMutex());
|
||||
WindowTable* activeWindows = MediaManager::Get()->GetActiveWindows();
|
||||
if (activeWindows->Get(mWindowID)) {
|
||||
// XPConnect is a magical unicorn.
|
||||
success->OnSuccess(mFile);
|
||||
}
|
||||
if (!(MediaManager::Get()->IsWindowStillActive(mWindowID))) {
|
||||
return NS_OK;
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
success->OnSuccess(mFile);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -252,19 +249,20 @@ public:
|
||||
|
||||
nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
|
||||
(nsGlobalWindow::GetInnerWindowWithId(mWindowID));
|
||||
WindowTable* activeWindows = MediaManager::Get()->GetActiveWindows();
|
||||
{
|
||||
MutexAutoLock lock(MediaManager::Get()->GetMutex());
|
||||
|
||||
if (!stream) {
|
||||
if (activeWindows->Get(mWindowID)) {
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
|
||||
LOG(("Returning error for getUserMedia() - no stream"));
|
||||
error->OnError(NS_LITERAL_STRING("NO_STREAM"));
|
||||
if (!(MediaManager::Get()->IsWindowStillActive(mWindowID))) {
|
||||
return NS_OK;
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
|
||||
LOG(("Returning error for getUserMedia() - no stream"));
|
||||
error->OnError(NS_LITERAL_STRING("NO_STREAM"));
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (window && window->GetExtantDoc()) {
|
||||
stream->CombineWithPrincipal(window->GetExtantDoc()->NodePrincipal());
|
||||
}
|
||||
@ -295,13 +293,13 @@ public:
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success(mSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
|
||||
|
||||
{
|
||||
MutexAutoLock lock(MediaManager::Get()->GetMutex());
|
||||
if (activeWindows->Get(mWindowID)) {
|
||||
LOG(("Returning success for getUserMedia()"));
|
||||
success->OnSuccess(static_cast<nsIDOMLocalMediaStream*>(stream));
|
||||
}
|
||||
if (!(MediaManager::Get()->IsWindowStillActive(mWindowID))) {
|
||||
return NS_OK;
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
LOG(("Returning success for getUserMedia()"));
|
||||
success->OnSuccess(static_cast<nsIDOMLocalMediaStream*>(stream));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -435,9 +433,12 @@ public:
|
||||
Denied()
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
// This is safe since we're on main-thread, and the window can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
|
||||
error->OnError(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
} else {
|
||||
// This will re-check the window being alive on main-thread
|
||||
NS_DispatchToMainThread(new ErrorCallbackRunnable(
|
||||
mSuccess, mError, NS_LITERAL_STRING("PERMISSION_DENIED"), mWindowID
|
||||
));
|
||||
@ -789,51 +790,49 @@ MediaManager::GetUserMedia(bool aPrivileged, nsPIDOMWindow* aWindow,
|
||||
// when this window is closed or navigated away from.
|
||||
uint64_t windowID = aWindow->WindowID();
|
||||
nsRefPtr<GetUserMediaRunnable> gUMRunnable;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
StreamListeners* listeners = mActiveWindows.Get(windowID);
|
||||
if (!listeners) {
|
||||
listeners = new StreamListeners;
|
||||
mActiveWindows.Put(windowID, listeners);
|
||||
}
|
||||
|
||||
// Developer preference for turning off permission check.
|
||||
if (Preferences::GetBool("media.navigator.permission.disabled", false)) {
|
||||
aPrivileged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass runnables along to GetUserMediaRunnable so it can add the
|
||||
* MediaStreamListener to the runnable list. The last argument can
|
||||
* optionally be a MediaDevice object, which should provided if one was
|
||||
* selected by the user via the UI, or was provided by privileged code
|
||||
* via the device: attribute via nsIMediaStreamOptions.
|
||||
*
|
||||
* If a fake stream was requested, we force the use of the default backend.
|
||||
*/
|
||||
if (fake) {
|
||||
// Fake stream from default backend.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, onSuccess.forget(), onError.forget(), listeners,
|
||||
windowID, new MediaEngineDefault()
|
||||
);
|
||||
} else if (audiodevice || videodevice) {
|
||||
// Stream from provided device.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
|
||||
windowID,
|
||||
static_cast<MediaDevice*>(audiodevice.get()),
|
||||
static_cast<MediaDevice*>(videodevice.get())
|
||||
);
|
||||
} else {
|
||||
// Stream from default device from WebRTC backend.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
|
||||
windowID
|
||||
);
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
StreamListeners* listeners = GetActiveWindows()->Get(windowID);
|
||||
if (!listeners) {
|
||||
listeners = new StreamListeners;
|
||||
GetActiveWindows()->Put(windowID, listeners);
|
||||
}
|
||||
|
||||
// Developer preference for turning off permission check.
|
||||
if (Preferences::GetBool("media.navigator.permission.disabled", false)) {
|
||||
aPrivileged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass runnables along to GetUserMediaRunnable so it can add the
|
||||
* MediaStreamListener to the runnable list. The last argument can
|
||||
* optionally be a MediaDevice object, which should provided if one was
|
||||
* selected by the user via the UI, or was provided by privileged code
|
||||
* via the device: attribute via nsIMediaStreamOptions.
|
||||
*
|
||||
* If a fake stream was requested, we force the use of the default backend.
|
||||
*/
|
||||
if (fake) {
|
||||
// Fake stream from default backend.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, onSuccess.forget(), onError.forget(), listeners,
|
||||
windowID, new MediaEngineDefault()
|
||||
);
|
||||
} else if (audiodevice || videodevice) {
|
||||
// Stream from provided device.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
|
||||
windowID,
|
||||
static_cast<MediaDevice*>(audiodevice.get()),
|
||||
static_cast<MediaDevice*>(videodevice.get())
|
||||
);
|
||||
} else {
|
||||
// Stream from default device from WebRTC backend.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
|
||||
windowID
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
if (picture) {
|
||||
@ -844,7 +843,6 @@ MediaManager::GetUserMedia(bool aPrivileged, nsPIDOMWindow* aWindow,
|
||||
#else
|
||||
// XXX No full support for picture in Desktop yet (needs proper UI)
|
||||
if (aPrivileged || fake) {
|
||||
(void) MediaManager::GetThread();
|
||||
mMediaThread->Dispatch(gUMRunnable, NS_DISPATCH_NORMAL);
|
||||
} else {
|
||||
// Ask for user permission, and dispatch runnable (or not) when a response
|
||||
@ -865,10 +863,7 @@ MediaManager::GetUserMedia(bool aPrivileged, nsPIDOMWindow* aWindow,
|
||||
NS_ConvertUTF8toUTF16 callID(buffer);
|
||||
|
||||
// Store the current callback.
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mActiveCallbacks.Put(callID, gUMRunnable);
|
||||
}
|
||||
mActiveCallbacks.Put(callID, gUMRunnable);
|
||||
|
||||
// Construct JSON structure with both the windowID and the callID.
|
||||
nsAutoString data;
|
||||
@ -922,6 +917,8 @@ MediaManager::GetBackend()
|
||||
{
|
||||
// Plugin backends as appropriate. The default engine also currently
|
||||
// includes picture support for Android.
|
||||
// This IS called off main-thread.
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (!mBackend) {
|
||||
#if defined(MOZ_WEBRTC)
|
||||
mBackend = new MediaEngineWebRTC();
|
||||
@ -929,39 +926,33 @@ MediaManager::GetBackend()
|
||||
mBackend = new MediaEngineDefault();
|
||||
#endif
|
||||
}
|
||||
|
||||
return mBackend;
|
||||
}
|
||||
|
||||
WindowTable*
|
||||
MediaManager::GetActiveWindows()
|
||||
{
|
||||
return &mActiveWindows;
|
||||
}
|
||||
|
||||
void
|
||||
MediaManager::OnNavigation(uint64_t aWindowID)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "OnNavigation called off main thread");
|
||||
|
||||
// Invalidate this window. The runnables check this value before making
|
||||
// a call to content.
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
StreamListeners* listeners = mActiveWindows.Get(aWindowID);
|
||||
if (!listeners) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t length = listeners->Length();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
nsRefPtr<GetUserMediaCallbackMediaStreamListener> listener =
|
||||
listeners->ElementAt(i);
|
||||
listener->Invalidate();
|
||||
listener = nullptr;
|
||||
}
|
||||
listeners->Clear();
|
||||
|
||||
mActiveWindows.Remove(aWindowID);
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be added to from the main-thread (see OnNavigation)
|
||||
StreamListeners* listeners = GetActiveWindows()->Get(aWindowID);
|
||||
if (!listeners) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t length = listeners->Length();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
nsRefPtr<GetUserMediaCallbackMediaStreamListener> listener =
|
||||
listeners->ElementAt(i);
|
||||
listener->Invalidate();
|
||||
}
|
||||
listeners->Clear();
|
||||
|
||||
GetActiveWindows()->Remove(aWindowID);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -979,7 +970,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
// Close off any remaining active windows.
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mActiveWindows.Clear();
|
||||
GetActiveWindows()->Clear();
|
||||
mActiveCallbacks.Clear();
|
||||
sSingleton = nullptr;
|
||||
}
|
||||
@ -990,15 +981,10 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
if (!strcmp(aTopic, "getUserMedia:response:allow")) {
|
||||
nsString key(aData);
|
||||
nsRefPtr<nsRunnable> runnable;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (!mActiveCallbacks.Get(key, getter_AddRefs(runnable))) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!mActiveCallbacks.Get(key, getter_AddRefs(runnable))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Reuse the same thread to save memory.
|
||||
(void) MediaManager::GetThread();
|
||||
mActiveCallbacks.Remove(key);
|
||||
|
||||
if (aSubject) {
|
||||
// A particular device was chosen by the user.
|
||||
@ -1019,26 +1005,22 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
}
|
||||
}
|
||||
|
||||
// Reuse the same thread to save memory.
|
||||
mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mActiveCallbacks.Remove(key);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "getUserMedia:response:deny")) {
|
||||
nsString key(aData);
|
||||
nsRefPtr<nsRunnable> runnable;
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mActiveCallbacks.Get(key, getter_AddRefs(runnable))) {
|
||||
GetUserMediaRunnable* gUMRunnable =
|
||||
static_cast<GetUserMediaRunnable*>(runnable.get());
|
||||
gUMRunnable->Denied();
|
||||
mActiveCallbacks.Remove(key);
|
||||
}
|
||||
if (!mActiveCallbacks.Get(key, getter_AddRefs(runnable))) {
|
||||
return NS_OK;
|
||||
}
|
||||
mActiveCallbacks.Remove(key);
|
||||
|
||||
GetUserMediaRunnable* gUMRunnable =
|
||||
static_cast<GetUserMediaRunnable*>(runnable.get());
|
||||
gUMRunnable->Denied();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -275,6 +275,9 @@ public:
|
||||
if (!sSingleton) {
|
||||
sSingleton = new MediaManager();
|
||||
|
||||
NS_NewThread(getter_AddRefs(sSingleton->mMediaThread));
|
||||
MM_LOG(("New Media thread for gum"));
|
||||
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only create MediaManager on main thread");
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
obs->AddObserver(sSingleton, "xpcom-shutdown", false);
|
||||
@ -283,23 +286,19 @@ public:
|
||||
}
|
||||
return sSingleton;
|
||||
}
|
||||
static Mutex& GetMutex() {
|
||||
return Get()->mMutex;
|
||||
}
|
||||
static nsIThread* GetThread() {
|
||||
MutexAutoLock lock(Get()->mMutex); // only need to call Get() once
|
||||
if (!sSingleton->mMediaThread) {
|
||||
NS_NewThread(getter_AddRefs(sSingleton->mMediaThread));
|
||||
MM_LOG(("New Media thread for gum"));
|
||||
}
|
||||
return sSingleton->mMediaThread;
|
||||
return Get()->mMediaThread;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
MediaEngine* GetBackend();
|
||||
WindowTable* GetActiveWindows();
|
||||
bool IsWindowStillActive(uint64_t aWindowId) {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
|
||||
|
||||
return !!mActiveWindows.Get(aWindowId);
|
||||
}
|
||||
|
||||
nsresult GetUserMedia(bool aPrivileged, nsPIDOMWindow* aWindow,
|
||||
nsIMediaStreamOptions* aParams,
|
||||
@ -311,11 +310,16 @@ public:
|
||||
void OnNavigation(uint64_t aWindowID);
|
||||
|
||||
private:
|
||||
WindowTable *GetActiveWindows() {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
|
||||
return &mActiveWindows;
|
||||
};
|
||||
|
||||
// Make private because we want only one instance of this class
|
||||
MediaManager()
|
||||
: mMutex("mozilla::MediaManager")
|
||||
, mBackend(nullptr)
|
||||
, mMediaThread(nullptr) {
|
||||
: mMediaThread(nullptr)
|
||||
, mMutex("mozilla::MediaManager")
|
||||
, mBackend(nullptr) {
|
||||
mActiveWindows.Init();
|
||||
mActiveCallbacks.Init();
|
||||
};
|
||||
@ -324,12 +328,15 @@ private:
|
||||
delete mBackend;
|
||||
};
|
||||
|
||||
// ONLY access from MainThread so we don't need to lock
|
||||
WindowTable mActiveWindows;
|
||||
nsRefPtrHashtable<nsStringHashKey, nsRunnable> mActiveCallbacks;
|
||||
// Always exists
|
||||
nsCOMPtr<nsIThread> mMediaThread;
|
||||
|
||||
Mutex mMutex;
|
||||
// protected with mMutex:
|
||||
MediaEngine* mBackend;
|
||||
nsCOMPtr<nsIThread> mMediaThread;
|
||||
WindowTable mActiveWindows;
|
||||
nsRefPtrHashtable<nsStringHashKey, nsRunnable> mActiveCallbacks;
|
||||
|
||||
static nsRefPtr<MediaManager> sSingleton;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user