зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1586057 - Avoid stepping on docShells of unrelated docs in MediaManager device stopping code. r=bzbarsky,pehrsons
Differential Revision: https://phabricator.services.mozilla.com/D52427 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
b439b62977
Коммит
94286593e7
|
@ -2187,9 +2187,11 @@ void MediaManager::DeviceListChanged() {
|
|||
deviceIDs.AppendElement(id);
|
||||
}
|
||||
}
|
||||
|
||||
// For any removed devices, notify their listeners cleanly that the
|
||||
// source has stopped, so JS knows and usage indicators update.
|
||||
for (auto& id : mDeviceIDs) {
|
||||
if (deviceIDs.Contains(id)) {
|
||||
// Device has not been removed
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2197,11 +2199,25 @@ void MediaManager::DeviceListChanged() {
|
|||
nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
|
||||
nsGlobalWindowInner::GetWindowsTable();
|
||||
if (!windowsById) {
|
||||
// We're in shutdown
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
|
||||
nsGlobalWindowInner* window = iter.Data();
|
||||
if (!window->IsCurrentInnerWindow()) {
|
||||
// Ignore non-current inner windows
|
||||
continue;
|
||||
}
|
||||
if (!window->GetOuterWindow()->IsTopLevelWindow()) {
|
||||
// Ignore non-top-level inner windows, to avoid hitting them
|
||||
// twice, since we'll be using IterateWindowListeners(). This
|
||||
// shouldn't miss any iframes, as they generally can't be
|
||||
// removed from DOM without OnNavigation. If it does miss them
|
||||
// OnNavigation does a comparable job (minus notifying the JS
|
||||
// that's about to be unloaded).
|
||||
continue;
|
||||
}
|
||||
IterateWindowListeners(
|
||||
window,
|
||||
[&id](const RefPtr<GetUserMediaWindowListener>& aListener) {
|
||||
|
@ -2234,7 +2250,7 @@ nsresult MediaManager::GenerateUUID(nsAString& aResult) {
|
|||
|
||||
static bool IsFullyActive(nsPIDOMWindowInner* aWindow) {
|
||||
while (true) {
|
||||
if (!aWindow) {
|
||||
if (!aWindow || nsGlobalWindowInner::Cast(aWindow)->IsDying()) {
|
||||
return false;
|
||||
}
|
||||
Document* document = aWindow->GetExtantDoc();
|
||||
|
@ -3368,6 +3384,12 @@ void MediaManager::OnNavigation(uint64_t aWindowID) {
|
|||
// be added to from the main-thread
|
||||
auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowID);
|
||||
if (window) {
|
||||
// We have cleanup to do when we're the current window. OnNavigation is also
|
||||
// called by nsGlobalWindowInner::FreeInnerObjects, which MAY happen later
|
||||
// when window is not current. In that case, cleanup has already happened.
|
||||
if (!window->IsCurrentInnerWindow()) {
|
||||
return;
|
||||
}
|
||||
IterateWindowListeners(
|
||||
window, [self = RefPtr<MediaManager>(this),
|
||||
windowID = DebugOnly<decltype(aWindowID)>(aWindowID)](
|
||||
|
@ -3895,11 +3917,11 @@ MediaManager::SanitizeDeviceIds(int64_t aSinceWhen) {
|
|||
}
|
||||
|
||||
void MediaManager::StopScreensharing(uint64_t aWindowID) {
|
||||
// We need to stop window/screensharing for all streams in all innerwindows
|
||||
// that correspond to that outerwindow.
|
||||
// We need to stop window/screensharing for all streams in this innerwindow
|
||||
// and all its sub frames.
|
||||
|
||||
auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowID);
|
||||
if (!window) {
|
||||
if (!window || !window->IsCurrentInnerWindow()) {
|
||||
return;
|
||||
}
|
||||
IterateWindowListeners(
|
||||
|
@ -3913,29 +3935,29 @@ void MediaManager::IterateWindowListeners(nsPIDOMWindowInner* aWindow,
|
|||
const FunctionType& aCallback) {
|
||||
// Iterate the docshell tree to find all the child windows, and for each
|
||||
// invoke the callback
|
||||
if (aWindow) {
|
||||
{
|
||||
uint64_t windowID = aWindow->WindowID();
|
||||
RefPtr<GetUserMediaWindowListener> listener = GetWindowListener(windowID);
|
||||
if (listener) {
|
||||
aCallback(listener);
|
||||
}
|
||||
// NB: `listener` might have been destroyed.
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWindow);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWindow->IsCurrentInnerWindow());
|
||||
{
|
||||
uint64_t windowID = aWindow->WindowID();
|
||||
RefPtr<GetUserMediaWindowListener> listener = GetWindowListener(windowID);
|
||||
if (listener) {
|
||||
aCallback(listener);
|
||||
}
|
||||
// NB: `listener` might have been destroyed.
|
||||
}
|
||||
|
||||
// iterate any children of *this* window (iframes, etc)
|
||||
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
||||
if (docShell) {
|
||||
int32_t i, count;
|
||||
docShell->GetInProcessChildCount(&count);
|
||||
for (i = 0; i < count; ++i) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> item;
|
||||
docShell->GetInProcessChildAt(i, getter_AddRefs(item));
|
||||
nsCOMPtr<nsPIDOMWindowOuter> winOuter =
|
||||
item ? item->GetWindow() : nullptr;
|
||||
|
||||
if (winOuter) {
|
||||
IterateWindowListeners(winOuter->GetCurrentInnerWindow(), aCallback);
|
||||
// iterate any children of *this* window (iframes, etc)
|
||||
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
||||
if (docShell) {
|
||||
int32_t i, count;
|
||||
docShell->GetInProcessChildCount(&count);
|
||||
for (i = 0; i < count; ++i) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> item;
|
||||
docShell->GetInProcessChildAt(i, getter_AddRefs(item));
|
||||
nsCOMPtr<nsPIDOMWindowOuter> child = item ? item->GetWindow() : nullptr;
|
||||
if (child) {
|
||||
if (auto* innerChild = child->GetCurrentInnerWindow()) {
|
||||
IterateWindowListeners(innerChild, aCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче