$OpenBSD$ index 9018740..9deac4a 100644 --- dom/media/MediaManager.cpp.orig Fri Feb 20 15:40:37 2015 +++ dom/media/MediaManager.cpp Fri Feb 20 15:40:37 2015 @@ -1579,10 +1579,33 @@ MediaManager::GetBackend(uint64_t aWindowId) 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(); + } + aListeners->Clear(); + aThis->RemoveWindowID(aWindowID); + } +} + + void MediaManager::OnNavigation(uint64_t aWindowID) { NS_ASSERTION(NS_IsMainThread(), "OnNavigation called off main thread"); + LOG(("OnNavigation for %llu", aWindowID)); // Invalidate this window. The runnables check this value before making // a call to content. @@ -1597,24 +1620,13 @@ MediaManager::OnNavigation(uint64_t aWindowID) // This is safe since we're on main-thread, and the windowlist can only // be added to from the main-thread - StreamListeners* listeners = GetWindowListeners(aWindowID); - if (!listeners) { - return; - } - - uint32_t length = listeners->Length(); - for (uint32_t i = 0; i < length; i++) { - nsRefPtr listener = - listeners->ElementAt(i); - if (listener->Stream()) { // aka HasBeenActivate()ed - listener->Invalidate(); - } - listener->Remove(); + nsPIDOMWindow *window = static_cast + (nsGlobalWindow::GetInnerWindowWithId(aWindowID)); + if (window) { + IterateWindowListeners(window, StopSharingCallback, nullptr); + } else { + RemoveWindowID(aWindowID); } - listeners->Clear(); - - RemoveWindowID(aWindowID); - // listeners has been deleted } void @@ -1875,59 +1887,79 @@ MediaManager::GetActiveMediaCaptureWindows(nsISupportsArray **aArray) return NS_OK; } +// XXX flags might be better... +struct CaptureWindowStateData { + bool *mVideo; + bool *mAudio; +}; + +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; + } + } + } +} + + NS_IMETHODIMP MediaManager::MediaCaptureWindowState(nsIDOMWindow* aWindow, bool* aVideo, bool* aAudio) { NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); + struct CaptureWindowStateData data; + data.mVideo = aVideo; + data.mAudio = aAudio; + *aVideo = false; *aAudio = false; - nsresult rv = MediaCaptureWindowStateInternal(aWindow, aVideo, aAudio); -#ifdef DEBUG nsCOMPtr piWin = do_QueryInterface(aWindow); + if (piWin) { + IterateWindowListeners(piWin, CaptureWindowStateCallback, &data); + } +#ifdef DEBUG LOG(("%s: window %lld capturing %s %s", __FUNCTION__, piWin ? piWin->WindowID() : -1, *aVideo ? "video" : "", *aAudio ? "audio" : "")); #endif - return rv; + return NS_OK; } -nsresult -MediaManager::MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo, - bool* aAudio) +// lets us do all sorts of things to the listeners +void +MediaManager::IterateWindowListeners(nsPIDOMWindow *aWindow, + WindowListenerCallback aCallback, + void *aData) { - // 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. + // Iterate the docshell tree to find all the child windows, and for each + // invoke the callback nsCOMPtr piWin = do_QueryInterface(aWindow); if (piWin) { - if (piWin->GetCurrentInnerWindow() || piWin->IsInnerWindow()) { + if (piWin->IsInnerWindow() || piWin->GetCurrentInnerWindow()) { uint64_t windowID; - if (piWin->GetCurrentInnerWindow()) { - windowID = piWin->GetCurrentInnerWindow()->WindowID(); - } else { + 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 listener = - listeners->ElementAt(i); - if (listener->CapturingVideo()) { - *aVideo = true; - } - if (listener->CapturingAudio()) { - *aAudio = true; - } - if (*aAudio && *aVideo) { - return NS_OK; // no need to continue iterating - } - } - } + // pass listeners so it can modify/delete the list + (*aCallback)(this, windowID, listeners, aData); } // iterate any children of *this* window (iframes, etc) @@ -1940,14 +1972,12 @@ MediaManager::MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVide docShell->GetChildAt(i, getter_AddRefs(item)); nsCOMPtr win = do_GetInterface(item); - MediaCaptureWindowStateInternal(win, aVideo, aAudio); - if (*aAudio && *aVideo) { - return NS_OK; // no need to continue iterating + if (win) { + IterateWindowListeners(win, aCallback, aData); } } } } - return NS_OK; } void