Bug 1050802: Backend to allow stopping sharing for screen/window for a WindowID r=jib

This commit is contained in:
Randell Jesup 2014-08-22 10:27:16 +01:00
parent 6aeef44c14
commit 74c0fb3f1e
2 changed files with 115 additions and 10 deletions

View File

@ -1992,13 +1992,23 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
} else if (!strcmp(aTopic, "getUserMedia:revoke")) {
nsresult rv;
uint64_t windowID = nsString(aData).ToInteger64(&rv);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_SUCCEEDED(rv)) {
LOG(("Revoking MediaCapture access for window %llu",windowID));
OnNavigation(windowID);
// may be windowid or screen:windowid
nsDependentString data(aData);
if (Substring(data, 0, strlen("screen:")).EqualsLiteral("screen:")) {
uint64_t windowID = PromiseFlatString(Substring(data, strlen("screen:"))).ToInteger64(&rv);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_SUCCEEDED(rv)) {
LOG(("Revoking Screeen/windowCapture access for window %llu", windowID));
StopScreensharing(windowID);
}
} else {
uint64_t windowID = nsString(aData).ToInteger64(&rv);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_SUCCEEDED(rv)) {
LOG(("Revoking MediaCapture access for window %llu", windowID));
OnNavigation(windowID);
}
}
return NS_OK;
}
#ifdef MOZ_WIDGET_GONK
@ -2148,6 +2158,67 @@ MediaManager::MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVide
return NS_OK;
}
// XXX abstract out the iteration over all children and provide a function pointer and data ptr
void
MediaManager::StopScreensharing(uint64_t aWindowID)
{
// We need to stop window/screensharing for all streams in all innerwindows that
// correspond to that outerwindow.
nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
(nsGlobalWindow::GetInnerWindowWithId(aWindowID));
if (!window) {
return;
}
StopScreensharing(window);
}
void
MediaManager::StopScreensharing(nsPIDOMWindow *aWindow)
{
// We need to stop window/screensharing for all streams in all innerwindows that
// correspond to that outerwindow.
// Iterate the docshell tree to find all the child windows, find
// all the listeners for each one, and tell them to stop
// window/screensharing
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
if (piWin) {
if (piWin->IsInnerWindow() || piWin->GetCurrentInnerWindow()) {
uint64_t windowID;
if (piWin->IsInnerWindow()) {
windowID = piWin->WindowID();
} else {
windowID = piWin->GetCurrentInnerWindow()->WindowID();
}
StreamListeners* listeners = GetActiveWindows()->Get(windowID);
if (listeners) {
uint32_t length = listeners->Length();
for (uint32_t i = 0; i < length; ++i) {
listeners->ElementAt(i)->StopScreenWindowSharing();
}
}
}
// iterate any children of *this* window (iframes, etc)
nsCOMPtr<nsIDocShell> docShell = piWin->GetDocShell();
if (docShell) {
int32_t i, count;
docShell->GetChildCount(&count);
for (i = 0; i < count; ++i) {
nsCOMPtr<nsIDocShellTreeItem> item;
docShell->GetChildAt(i, getter_AddRefs(item));
nsCOMPtr<nsPIDOMWindow> win = item ? item->GetWindow() : nullptr;
if (win) {
StopScreensharing(win);
}
}
}
}
}
void
MediaManager::StopMediaStreams()
{
@ -2182,6 +2253,26 @@ GetUserMediaCallbackMediaStreamListener::Invalidate()
mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
}
// Doesn't kill audio
// XXX refactor to combine with Invalidate()?
void
GetUserMediaCallbackMediaStreamListener::StopScreenWindowSharing()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
if (mVideoSource && !mStopped &&
(mVideoSource->GetMediaSource() == MediaSourceType::Screen ||
mVideoSource->GetMediaSource() == MediaSourceType::Window)) {
// Stop the whole stream if there's no audio; just the video track if we have both
nsRefPtr<MediaOperationRunnable> runnable(
new MediaOperationRunnable(mAudioSource ? MEDIA_STOP_TRACK : MEDIA_STOP,
this, nullptr, nullptr,
nullptr, mVideoSource,
mFinished, mWindowID, nullptr));
mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
}
}
// Called from the MediaStreamGraph thread
void
GetUserMediaCallbackMediaStreamListener::NotifyFinished(MediaStreamGraph* aGraph)
@ -2242,6 +2333,9 @@ GetUserMediaNotificationEvent::Run()
mListener->SetStopped();
}
break;
case STOPPED_TRACK:
msg = NS_LITERAL_STRING("shutdown");
break;
}
nsCOMPtr<nsPIDOMWindow> window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);

View File

@ -99,6 +99,8 @@ public:
return mStream->AsSourceStream();
}
void StopScreenWindowSharing();
// mVideo/AudioSource are set by Activate(), so we assume they're capturing
// if set and represent a real capture device.
bool CapturingVideo()
@ -119,13 +121,13 @@ public:
bool CapturingScreen()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
return mVideoSource && !mStopped &&
return mVideoSource && !mStopped && !mVideoSource->IsAvailable() &&
mVideoSource->GetMediaSource() == MediaSourceType::Screen;
}
bool CapturingWindow()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
return mVideoSource && !mStopped &&
return mVideoSource && !mStopped && !mVideoSource->IsAvailable() &&
mVideoSource->GetMediaSource() == MediaSourceType::Window;
}
@ -246,7 +248,8 @@ class GetUserMediaNotificationEvent: public nsRunnable
public:
enum GetUserMediaStatus {
STARTING,
STOPPING
STOPPING,
STOPPED_TRACK
};
GetUserMediaNotificationEvent(GetUserMediaCallbackMediaStreamListener* aListener,
GetUserMediaStatus aStatus,
@ -283,6 +286,7 @@ class GetUserMediaNotificationEvent: public nsRunnable
typedef enum {
MEDIA_START,
MEDIA_STOP,
MEDIA_STOP_TRACK,
MEDIA_DIRECT_LISTENERS
} MediaOperation;
@ -426,6 +430,7 @@ public:
break;
case MEDIA_STOP:
case MEDIA_STOP_TRACK:
{
NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
if (mAudioSource) {
@ -440,9 +445,12 @@ public:
if (mBool) {
source->Finish();
}
nsIRunnable *event =
new GetUserMediaNotificationEvent(mListener,
GetUserMediaNotificationEvent::STOPPING,
mType == MEDIA_STOP ?
GetUserMediaNotificationEvent::STOPPING :
GetUserMediaNotificationEvent::STOPPED_TRACK,
mAudioSource != nullptr,
mVideoSource != nullptr,
mWindowID);
@ -595,6 +603,9 @@ private:
bool* aAudio, bool *aScreenShare,
bool* aWindowShare);
void StopScreensharing(uint64_t aWindowID);
void StopScreensharing(nsPIDOMWindow *aWindow);
void StopMediaStreams();
// ONLY access from MainThread so we don't need to lock