зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1062876: refactor window iteration code for MediaManager r=jib
This commit is contained in:
Родитель
bb7cc33cc1
Коммит
233163862b
|
@ -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();
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче