Bug 1062876: refactor window iteration code for MediaManager r=jib

This commit is contained in:
Randell Jesup 2014-09-19 17:24:28 -04:00
Родитель bb7cc33cc1
Коммит 233163862b
2 изменённых файлов: 116 добавлений и 102 удалений

Просмотреть файл

@ -1893,10 +1893,34 @@ MediaManager::GetBackend(uint64_t aWindowId)
return mBackend; return mBackend;
} }
static void
StopSharingCallback(MediaManager *aThis,
uint64_t aWindowID,
StreamListeners *aListeners,
void *aData)
{
if (aListeners) {
auto length = aListeners->Length();
for (size_t i = 0; i < length; ++i) {
GetUserMediaCallbackMediaStreamListener *listener = aListeners->ElementAt(i);
if (listener->Stream()) { // aka HasBeenActivate()ed
listener->Invalidate();
}
listener->Remove();
listener->StopScreenWindowSharing();
}
aListeners->Clear();
aThis->RemoveWindowID(aWindowID);
}
}
void void
MediaManager::OnNavigation(uint64_t aWindowID) MediaManager::OnNavigation(uint64_t aWindowID)
{ {
NS_ASSERTION(NS_IsMainThread(), "OnNavigation called off main thread"); NS_ASSERTION(NS_IsMainThread(), "OnNavigation called off main thread");
LOG(("OnNavigation for %llu", aWindowID));
// Invalidate this window. The runnables check this value before making // Invalidate this window. The runnables check this value before making
// a call to content. // a call to content.
@ -1911,24 +1935,13 @@ MediaManager::OnNavigation(uint64_t aWindowID)
// This is safe since we're on main-thread, and the windowlist can only // This is safe since we're on main-thread, and the windowlist can only
// be added to from the main-thread // be added to from the main-thread
StreamListeners* listeners = GetWindowListeners(aWindowID); nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
if (!listeners) { (nsGlobalWindow::GetInnerWindowWithId(aWindowID));
return; if (window) {
IterateWindowListeners(window, StopSharingCallback, nullptr);
} else {
RemoveWindowID(aWindowID);
} }
uint32_t length = listeners->Length();
for (uint32_t i = 0; i < length; i++) {
nsRefPtr<GetUserMediaCallbackMediaStreamListener> listener =
listeners->ElementAt(i);
if (listener->Stream()) { // aka HasBeenActivate()ed
listener->Invalidate();
}
listener->Remove();
}
listeners->Clear();
RemoveWindowID(aWindowID);
// listeners has been deleted
} }
void void
@ -2213,92 +2226,93 @@ MediaManager::GetActiveMediaCaptureWindows(nsISupportsArray **aArray)
return NS_OK; return NS_OK;
} }
// XXX flags might be better...
struct CaptureWindowStateData {
bool *mVideo;
bool *mAudio;
bool *mScreenShare;
bool *mWindowShare;
bool *mAppShare;
};
static void
CaptureWindowStateCallback(MediaManager *aThis,
uint64_t aWindowID,
StreamListeners *aListeners,
void *aData)
{
struct CaptureWindowStateData *data = (struct CaptureWindowStateData *) aData;
if (aListeners) {
auto length = aListeners->Length();
for (size_t i = 0; i < length; ++i) {
GetUserMediaCallbackMediaStreamListener *listener = aListeners->ElementAt(i);
if (listener->CapturingVideo()) {
*data->mVideo = true;
}
if (listener->CapturingAudio()) {
*data->mAudio = true;
}
if (listener->CapturingScreen()) {
*data->mScreenShare = true;
}
if (listener->CapturingWindow()) {
*data->mWindowShare = true;
}
if (listener->CapturingApplication()) {
*data->mAppShare = true;
}
}
}
}
NS_IMETHODIMP NS_IMETHODIMP
MediaManager::MediaCaptureWindowState(nsIDOMWindow* aWindow, bool* aVideo, MediaManager::MediaCaptureWindowState(nsIDOMWindow* aWindow, bool* aVideo,
bool* aAudio, bool *aScreenShare, bool* aAudio, bool *aScreenShare,
bool* aWindowShare, bool *aAppShare) bool* aWindowShare, bool *aAppShare)
{ {
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
struct CaptureWindowStateData data;
data.mVideo = aVideo;
data.mAudio = aAudio;
data.mScreenShare = aScreenShare;
data.mWindowShare = aWindowShare;
data.mAppShare = aAppShare;
*aVideo = false; *aVideo = false;
*aAudio = false; *aAudio = false;
*aScreenShare = false; *aScreenShare = false;
*aWindowShare = false; *aWindowShare = false;
*aAppShare = false; *aAppShare = false;
nsresult rv = MediaCaptureWindowStateInternal(aWindow, aVideo, aAudio, aScreenShare, aWindowShare, aAppShare);
#ifdef DEBUG
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow); nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
if (piWin) {
IterateWindowListeners(piWin, CaptureWindowStateCallback, &data);
}
#ifdef DEBUG
LOG(("%s: window %lld capturing %s %s %s %s %s", __FUNCTION__, piWin ? piWin->WindowID() : -1, LOG(("%s: window %lld capturing %s %s %s %s %s", __FUNCTION__, piWin ? piWin->WindowID() : -1,
*aVideo ? "video" : "", *aAudio ? "audio" : "", *aVideo ? "video" : "", *aAudio ? "audio" : "",
*aScreenShare ? "screenshare" : "", *aWindowShare ? "windowshare" : "", *aScreenShare ? "screenshare" : "", *aWindowShare ? "windowshare" : "",
*aAppShare ? "appshare" : "")); *aAppShare ? "appshare" : ""));
#endif #endif
return rv;
}
nsresult
MediaManager::MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo,
bool* aAudio, bool *aScreenShare,
bool* aWindowShare, bool *aAppShare)
{
// We need to return the union of 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, get the booleans, and merge the
// results.
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) {
nsRefPtr<GetUserMediaCallbackMediaStreamListener> listener =
listeners->ElementAt(i);
if (listener->CapturingVideo()) {
*aVideo = true;
}
if (listener->CapturingAudio()) {
*aAudio = true;
}
if (listener->CapturingScreen()) {
*aScreenShare = true;
}
if (listener->CapturingWindow()) {
*aWindowShare = true;
}
if (listener->CapturingApplication()) {
*aAppShare = true;
}
}
}
}
// 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;
MediaCaptureWindowStateInternal(win, aVideo, aAudio, aScreenShare, aWindowShare, aAppShare);
}
}
}
return NS_OK; return NS_OK;
} }
// XXX abstract out the iteration over all children and provide a function pointer and data ptr static void
StopScreensharingCallback(MediaManager *aThis,
uint64_t aWindowID,
StreamListeners *aListeners,
void *aData)
{
if (aListeners) {
auto length = aListeners->Length();
for (size_t i = 0; i < length; ++i) {
aListeners->ElementAt(i)->StopScreenWindowSharing();
}
}
}
void void
MediaManager::StopScreensharing(uint64_t aWindowID) MediaManager::StopScreensharing(uint64_t aWindowID)
@ -2311,18 +2325,17 @@ MediaManager::StopScreensharing(uint64_t aWindowID)
if (!window) { if (!window) {
return; return;
} }
StopScreensharing(window); IterateWindowListeners(window, &StopScreensharingCallback, nullptr);
} }
// lets us do all sorts of things to the listeners
void void
MediaManager::StopScreensharing(nsPIDOMWindow *aWindow) MediaManager::IterateWindowListeners(nsPIDOMWindow *aWindow,
WindowListenerCallback aCallback,
void *aData)
{ {
// We need to stop window/screensharing for all streams in all innerwindows that // Iterate the docshell tree to find all the child windows, and for each
// correspond to that outerwindow. // invoke the callback
// 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); nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
if (piWin) { if (piWin) {
if (piWin->IsInnerWindow() || piWin->GetCurrentInnerWindow()) { if (piWin->IsInnerWindow() || piWin->GetCurrentInnerWindow()) {
@ -2333,12 +2346,8 @@ MediaManager::StopScreensharing(nsPIDOMWindow *aWindow)
windowID = piWin->GetCurrentInnerWindow()->WindowID(); windowID = piWin->GetCurrentInnerWindow()->WindowID();
} }
StreamListeners* listeners = GetActiveWindows()->Get(windowID); StreamListeners* listeners = GetActiveWindows()->Get(windowID);
if (listeners) { // pass listeners so it can modify/delete the list
uint32_t length = listeners->Length(); (*aCallback)(this, windowID, listeners, aData);
for (uint32_t i = 0; i < length; ++i) {
listeners->ElementAt(i)->StopScreenWindowSharing();
}
}
} }
// iterate any children of *this* window (iframes, etc) // iterate any children of *this* window (iframes, etc)
@ -2352,13 +2361,14 @@ MediaManager::StopScreensharing(nsPIDOMWindow *aWindow)
nsCOMPtr<nsPIDOMWindow> win = item ? item->GetWindow() : nullptr; nsCOMPtr<nsPIDOMWindow> win = item ? item->GetWindow() : nullptr;
if (win) { if (win) {
StopScreensharing(win); IterateWindowListeners(win, aCallback, aData);
} }
} }
} }
} }
} }
void void
MediaManager::StopMediaStreams() MediaManager::StopMediaStreams()
{ {

Просмотреть файл

@ -528,6 +528,12 @@ public:
MediaEngineAudioSource* GetSource(); MediaEngineAudioSource* GetSource();
}; };
// we could add MediaManager if needed
typedef void (*WindowListenerCallback)(MediaManager *aThis,
uint64_t aWindowID,
StreamListeners *aListeners,
void *aData);
class MediaManager MOZ_FINAL : public nsIMediaManagerService, class MediaManager MOZ_FINAL : public nsIMediaManagerService,
public nsIObserver public nsIObserver
{ {
@ -600,12 +606,10 @@ private:
~MediaManager() {} ~MediaManager() {}
nsresult MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo,
bool* aAudio, bool *aScreenShare,
bool* aWindowShare, bool *aAppShare);
void StopScreensharing(uint64_t aWindowID); void StopScreensharing(uint64_t aWindowID);
void StopScreensharing(nsPIDOMWindow *aWindow); void IterateWindowListeners(nsPIDOMWindow *aWindow,
WindowListenerCallback aCallback,
void *aData);
void StopMediaStreams(); void StopMediaStreams();