зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1494675 - Merge SourceListener::Remove into SourceListener::Stop. r=padenot
Depends on: D24903 Differential Revision: https://phabricator.services.mozilla.com/D25114 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
8a27a07a02
Коммит
3d69980886
|
@ -335,20 +335,19 @@ class SourceListener : public SupportsWeakPtr<SourceListener> {
|
|||
RefPtr<SourceListenerPromise> InitializeAsync();
|
||||
|
||||
/**
|
||||
* Stops all live tracks, finishes the associated MediaStream and cleans up.
|
||||
* Stops all live tracks, finishes the associated MediaStream and cleans up
|
||||
* the weak reference to the associated window listener.
|
||||
* This will also tell the window listener to remove its hard reference to
|
||||
* this SourceListener, so any caller will need to keep its own hard ref.
|
||||
*/
|
||||
void Stop();
|
||||
|
||||
/**
|
||||
* Removes this SourceListener from its associated MediaStream and marks it
|
||||
* removed. Also removes the weak reference to the associated window listener.
|
||||
*/
|
||||
void Remove();
|
||||
|
||||
/**
|
||||
* Posts a task to stop the device associated with aTrackID and notifies the
|
||||
* associated window listener that a track was stopped.
|
||||
* Should this track be the last live one to be stopped, we'll also clean up.
|
||||
* Should this track be the last live one to be stopped, we'll also call Stop.
|
||||
* This might tell the window listener to remove its hard reference to this
|
||||
* SourceListener, so any caller will need to keep its own hard ref.
|
||||
*/
|
||||
void StopTrack(TrackID aTrackID);
|
||||
|
||||
|
@ -401,12 +400,6 @@ class SourceListener : public SupportsWeakPtr<SourceListener> {
|
|||
return mVideoDeviceState ? mVideoDeviceState->mDevice.get() : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on main thread after MediaStreamGraph notifies us that one of our
|
||||
* track listeners was removed as listener from its track in the graph.
|
||||
*/
|
||||
void NotifyRemoved(TrackID aTrackID);
|
||||
|
||||
bool Activated() const { return mStream; }
|
||||
|
||||
bool Stopped() const { return mStopped; }
|
||||
|
@ -441,10 +434,6 @@ class SourceListener : public SupportsWeakPtr<SourceListener> {
|
|||
// true after this listener has had all devices stopped. MainThread only.
|
||||
bool mStopped;
|
||||
|
||||
// true after this listener has been removed from its MediaStream.
|
||||
// MainThread only.
|
||||
bool mRemoved;
|
||||
|
||||
// never ever indirect off this; just for assertions
|
||||
PRThread* mMainThreadCheck;
|
||||
|
||||
|
@ -514,17 +503,6 @@ class GetUserMediaWindowListener {
|
|||
mActiveListeners.AppendElement(do_AddRef(aListener));
|
||||
}
|
||||
|
||||
// Can be invoked from EITHER MainThread or MSG thread
|
||||
void Stop() {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
for (auto& source : mActiveListeners) {
|
||||
source->Stop();
|
||||
}
|
||||
|
||||
// Once all tracks have stopped, that will trigger the chrome notification
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all SourceListeners from this window listener.
|
||||
* Removes this window listener from the list of active windows, so callers
|
||||
|
@ -533,7 +511,7 @@ class GetUserMediaWindowListener {
|
|||
void RemoveAll() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Shallow copy since SourceListener::Remove() will modify the arrays.
|
||||
// Shallow copy since SourceListener::Stop() will modify the arrays.
|
||||
nsTArray<RefPtr<SourceListener>> listeners(mInactiveListeners.Length() +
|
||||
mActiveListeners.Length());
|
||||
listeners.AppendElements(mInactiveListeners);
|
||||
|
@ -587,8 +565,8 @@ class GetUserMediaWindowListener {
|
|||
"A SourceListener should only be once in one of "
|
||||
"mInactiveListeners and mActiveListeners");
|
||||
|
||||
LOG("GUMWindowListener %p removing SourceListener %p.", this, aListener);
|
||||
aListener->Remove();
|
||||
LOG("GUMWindowListener %p stopping SourceListener %p.", this, aListener);
|
||||
aListener->Stop();
|
||||
|
||||
if (MediaDevice* removedDevice = aListener->GetVideoDevice()) {
|
||||
bool revokeVideoPermission = true;
|
||||
|
@ -654,6 +632,7 @@ class GetUserMediaWindowListener {
|
|||
this);
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1206,7 +1185,8 @@ class GetUserMediaStreamRunnable : public Runnable {
|
|||
|
||||
void Stop() override {
|
||||
if (mListener) {
|
||||
mListener->StopTrack(mTrackID);
|
||||
RefPtr<SourceListener> deathGrip(mListener);
|
||||
deathGrip->StopTrack(mTrackID);
|
||||
mListener = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -2164,6 +2144,7 @@ nsresult MediaManager::NotifyRecordingStatusChange(
|
|||
|
||||
obs->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
|
||||
"recording-device-events", nullptr);
|
||||
LOG("Sent recording-device-events for url '%s'", pageURL.get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2201,50 +2182,50 @@ void MediaManager::OnDeviceChange() {
|
|||
0, MediaSourceEnum::Camera, MediaSourceEnum::Microphone,
|
||||
MediaSinkEnum::Speaker, DeviceEnumerationType::Normal,
|
||||
DeviceEnumerationType::Normal, false, devices)
|
||||
->Then(GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[self, devices](bool) {
|
||||
if (!MediaManager::GetIfExists()) {
|
||||
return;
|
||||
}
|
||||
->Then(
|
||||
GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[self, devices](bool) {
|
||||
if (!MediaManager::GetIfExists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsString> deviceIDs;
|
||||
nsTArray<nsString> deviceIDs;
|
||||
|
||||
for (auto& device : *devices) {
|
||||
nsString id;
|
||||
device->GetId(id);
|
||||
id.ReplaceSubstring(NS_LITERAL_STRING("default: "),
|
||||
NS_LITERAL_STRING(""));
|
||||
if (!deviceIDs.Contains(id)) {
|
||||
deviceIDs.AppendElement(id);
|
||||
}
|
||||
}
|
||||
for (auto& device : *devices) {
|
||||
nsString id;
|
||||
device->GetId(id);
|
||||
id.ReplaceSubstring(NS_LITERAL_STRING("default: "),
|
||||
NS_LITERAL_STRING(""));
|
||||
if (!deviceIDs.Contains(id)) {
|
||||
deviceIDs.AppendElement(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& id : self->mDeviceIDs) {
|
||||
if (deviceIDs.Contains(id)) {
|
||||
continue;
|
||||
}
|
||||
for (auto& id : self->mDeviceIDs) {
|
||||
if (deviceIDs.Contains(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Stop the coresponding SourceListener
|
||||
nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
|
||||
nsGlobalWindowInner::GetWindowsTable();
|
||||
if (!windowsById) {
|
||||
continue;
|
||||
}
|
||||
// Stop the coresponding SourceListener
|
||||
nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
|
||||
nsGlobalWindowInner::GetWindowsTable();
|
||||
if (!windowsById) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto iter = windowsById->Iter(); !iter.Done();
|
||||
iter.Next()) {
|
||||
nsGlobalWindowInner* window = iter.Data();
|
||||
self->IterateWindowListeners(
|
||||
window->AsInner(),
|
||||
[&id](GetUserMediaWindowListener* aListener) {
|
||||
aListener->StopRawID(id);
|
||||
});
|
||||
}
|
||||
}
|
||||
for (auto iter = windowsById->Iter(); !iter.Done();
|
||||
iter.Next()) {
|
||||
nsGlobalWindowInner* window = iter.Data();
|
||||
self->IterateWindowListeners(
|
||||
window->AsInner(),
|
||||
[&id](const RefPtr<GetUserMediaWindowListener>&
|
||||
aListener) { aListener->StopRawID(id); });
|
||||
}
|
||||
}
|
||||
|
||||
self->mDeviceIDs = deviceIDs;
|
||||
},
|
||||
[](RefPtr<MediaMgrError>&& reason) {});
|
||||
self->mDeviceIDs = deviceIDs;
|
||||
},
|
||||
[](RefPtr<MediaMgrError>&& reason) {});
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -3420,13 +3401,8 @@ void MediaManager::OnNavigation(uint64_t aWindowID) {
|
|||
window->AsInner(),
|
||||
[self = RefPtr<MediaManager>(this),
|
||||
windowID = DebugOnly<decltype(aWindowID)>(aWindowID)](
|
||||
GetUserMediaWindowListener* aListener) {
|
||||
// Grab a strong ref since RemoveAll() might destroy the listener
|
||||
// mid-way when clearing the mActiveWindows reference.
|
||||
RefPtr<GetUserMediaWindowListener> listener(aListener);
|
||||
|
||||
listener->Stop();
|
||||
listener->RemoveAll();
|
||||
const RefPtr<GetUserMediaWindowListener>& aListener) {
|
||||
aListener->RemoveAll();
|
||||
MOZ_ASSERT(!self->GetWindowListener(windowID));
|
||||
});
|
||||
} else {
|
||||
|
@ -3599,7 +3575,6 @@ void MediaManager::Shutdown() {
|
|||
listeners.AppendElement(iter.UserData());
|
||||
}
|
||||
for (auto& listener : listeners) {
|
||||
listener->Stop();
|
||||
listener->RemoveAll();
|
||||
}
|
||||
}
|
||||
|
@ -3898,23 +3873,24 @@ MediaManager::MediaCaptureWindowState(nsIDOMWindow* aCapturedWindow,
|
|||
|
||||
nsCOMPtr<nsPIDOMWindowInner> piWin = do_QueryInterface(aCapturedWindow);
|
||||
if (piWin) {
|
||||
IterateWindowListeners(piWin, [&camera, µphone, &screen, &window,
|
||||
&application, &browser](
|
||||
GetUserMediaWindowListener* aListener) {
|
||||
camera = CombineCaptureState(
|
||||
camera, aListener->CapturingSource(MediaSourceEnum::Camera));
|
||||
microphone = CombineCaptureState(
|
||||
microphone, aListener->CapturingSource(MediaSourceEnum::Microphone));
|
||||
screen = CombineCaptureState(
|
||||
screen, aListener->CapturingSource(MediaSourceEnum::Screen));
|
||||
window = CombineCaptureState(
|
||||
window, aListener->CapturingSource(MediaSourceEnum::Window));
|
||||
application = CombineCaptureState(
|
||||
application,
|
||||
aListener->CapturingSource(MediaSourceEnum::Application));
|
||||
browser = CombineCaptureState(
|
||||
browser, aListener->CapturingSource(MediaSourceEnum::Browser));
|
||||
});
|
||||
IterateWindowListeners(
|
||||
piWin, [&camera, µphone, &screen, &window, &application,
|
||||
&browser](const RefPtr<GetUserMediaWindowListener>& aListener) {
|
||||
camera = CombineCaptureState(
|
||||
camera, aListener->CapturingSource(MediaSourceEnum::Camera));
|
||||
microphone = CombineCaptureState(
|
||||
microphone,
|
||||
aListener->CapturingSource(MediaSourceEnum::Microphone));
|
||||
screen = CombineCaptureState(
|
||||
screen, aListener->CapturingSource(MediaSourceEnum::Screen));
|
||||
window = CombineCaptureState(
|
||||
window, aListener->CapturingSource(MediaSourceEnum::Window));
|
||||
application = CombineCaptureState(
|
||||
application,
|
||||
aListener->CapturingSource(MediaSourceEnum::Application));
|
||||
browser = CombineCaptureState(
|
||||
browser, aListener->CapturingSource(MediaSourceEnum::Browser));
|
||||
});
|
||||
}
|
||||
|
||||
*aCamera = FromCaptureState(camera);
|
||||
|
@ -3924,7 +3900,6 @@ MediaManager::MediaCaptureWindowState(nsIDOMWindow* aCapturedWindow,
|
|||
*aApplication = FromCaptureState(application);
|
||||
*aBrowser = FromCaptureState(browser);
|
||||
|
||||
#ifdef DEBUG
|
||||
LOG("%s: window %" PRIu64 " capturing %s %s %s %s %s %s", __FUNCTION__,
|
||||
piWin ? piWin->WindowID() : -1,
|
||||
*aCamera == nsIMediaManagerService::STATE_CAPTURE_ENABLED
|
||||
|
@ -3939,7 +3914,7 @@ MediaManager::MediaCaptureWindowState(nsIDOMWindow* aCapturedWindow,
|
|||
: ""),
|
||||
*aScreen ? "screenshare" : "", *aWindow ? "windowshare" : "",
|
||||
*aApplication ? "appshare" : "", *aBrowser ? "browsershare" : "");
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3962,7 +3937,9 @@ void MediaManager::StopScreensharing(uint64_t aWindowID) {
|
|||
}
|
||||
IterateWindowListeners(
|
||||
window->AsInner(),
|
||||
[](GetUserMediaWindowListener* aListener) { aListener->StopSharing(); });
|
||||
[](const RefPtr<GetUserMediaWindowListener>& aListener) {
|
||||
aListener->StopSharing();
|
||||
});
|
||||
}
|
||||
|
||||
template <typename FunctionType>
|
||||
|
@ -3973,7 +3950,7 @@ void MediaManager::IterateWindowListeners(nsPIDOMWindowInner* aWindow,
|
|||
if (aWindow) {
|
||||
{
|
||||
uint64_t windowID = aWindow->WindowID();
|
||||
GetUserMediaWindowListener* listener = GetWindowListener(windowID);
|
||||
RefPtr<GetUserMediaWindowListener> listener = GetWindowListener(windowID);
|
||||
if (listener) {
|
||||
aCallback(listener);
|
||||
}
|
||||
|
@ -4086,7 +4063,6 @@ bool MediaManager::IsActivelyCapturingOrHasAPermission(uint64_t aWindowId) {
|
|||
|
||||
SourceListener::SourceListener()
|
||||
: mStopped(false),
|
||||
mRemoved(false),
|
||||
mMainThreadCheck(nullptr),
|
||||
mPrincipalHandle(PRINCIPAL_HANDLE_NONE),
|
||||
mWindowListener(nullptr) {}
|
||||
|
@ -4246,45 +4222,31 @@ SourceListener::InitializeAsync() {
|
|||
void SourceListener::Stop() {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
if (mStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("SourceListener %p stopping", this);
|
||||
|
||||
// StopSharing() has some special logic, at least for audio capture.
|
||||
// It must be called when all tracks have stopped, before setting mStopped.
|
||||
StopSharing();
|
||||
|
||||
if (mStopped) {
|
||||
return;
|
||||
}
|
||||
mStopped = true;
|
||||
|
||||
MOZ_ASSERT(Activated(), "There are no devices or any source stream to stop");
|
||||
MOZ_ASSERT(mStream, "Can't end tracks. No source stream.");
|
||||
|
||||
if (mAudioDeviceState && !mAudioDeviceState->mStopped) {
|
||||
StopTrack(kAudioTrack);
|
||||
}
|
||||
if (mVideoDeviceState && !mVideoDeviceState->mStopped) {
|
||||
StopTrack(kVideoTrack);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceListener::Remove() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
LOG("SourceListener %p stopping", this);
|
||||
|
||||
if (mAudioDeviceState) {
|
||||
mAudioDeviceState->mDisableTimer->Cancel();
|
||||
if (!mAudioDeviceState->mStopped) {
|
||||
StopTrack(kAudioTrack);
|
||||
}
|
||||
}
|
||||
if (mVideoDeviceState) {
|
||||
mVideoDeviceState->mDisableTimer->Cancel();
|
||||
if (!mVideoDeviceState->mStopped) {
|
||||
StopTrack(kVideoTrack);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mStream || mRemoved) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("SourceListener %p removed on purpose", this);
|
||||
mRemoved = true; // RemoveListener is async, avoid races
|
||||
mWindowListener->Remove(this);
|
||||
mWindowListener = nullptr;
|
||||
}
|
||||
|
||||
|
@ -4311,14 +4273,14 @@ void SourceListener::StopTrack(TrackID aTrackID) {
|
|||
device->Deallocate();
|
||||
}));
|
||||
|
||||
MOZ_ASSERT(mWindowListener, "Should still have window listener");
|
||||
mWindowListener->ChromeAffectingStateChanged();
|
||||
|
||||
if ((!mAudioDeviceState || mAudioDeviceState->mStopped) &&
|
||||
(!mVideoDeviceState || mVideoDeviceState->mStopped)) {
|
||||
LOG("SourceListener %p this was the last track stopped", this);
|
||||
Stop();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mWindowListener, "Should still have window listener");
|
||||
mWindowListener->ChromeAffectingStateChanged();
|
||||
}
|
||||
|
||||
void SourceListener::GetSettingsFor(
|
||||
|
@ -4333,10 +4295,6 @@ void SourceListener::SetEnabledFor(TrackID aTrackID, bool aEnable) {
|
|||
MOZ_ASSERT(aTrackID == kAudioTrack || aTrackID == kVideoTrack,
|
||||
"Unknown track id");
|
||||
|
||||
if (mRemoved) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("SourceListener %p %s %s track %d", this,
|
||||
aEnable ? "enabling" : "disabling",
|
||||
aTrackID == kAudioTrack ? "audio" : "video", aTrackID);
|
||||
|
@ -4401,12 +4359,6 @@ void SourceListener::SetEnabledFor(TrackID aTrackID, bool aEnable) {
|
|||
this, aEnable ? "enabling" : "disabling",
|
||||
aTrackID == kAudioTrack ? "audio" : "video", aTrackID);
|
||||
|
||||
if (mRemoved) {
|
||||
// Listener was removed between timer resolving and this runnable.
|
||||
return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT,
|
||||
__func__);
|
||||
}
|
||||
|
||||
if (state.mStopped) {
|
||||
// Source was stopped between timer resolving and this runnable.
|
||||
return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT,
|
||||
|
@ -4501,12 +4453,12 @@ void SourceListener::SetEnabledFor(TrackID aTrackID, bool aEnable) {
|
|||
|
||||
void SourceListener::StopSharing() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(mWindowListener);
|
||||
|
||||
if (mStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(mWindowListener);
|
||||
LOG("SourceListener %p StopSharing", this);
|
||||
|
||||
if (mVideoDeviceState && (mVideoDeviceState->mDevice->GetMediaSource() ==
|
||||
|
@ -4538,27 +4490,6 @@ SourceMediaStream* SourceListener::GetSourceStream() {
|
|||
return mStream;
|
||||
}
|
||||
|
||||
void SourceListener::NotifyRemoved(TrackID aTrackID) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
LOG("Track %d for SourceListener %p removed", aTrackID, this);
|
||||
|
||||
StopTrack(aTrackID);
|
||||
|
||||
if (!mStopped) {
|
||||
// There are more live tracks that need to be stopped before removal.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mWindowListener) {
|
||||
// Removed explicitly before MSG's notification.
|
||||
return;
|
||||
}
|
||||
|
||||
mWindowListener->Remove(this);
|
||||
|
||||
MOZ_ASSERT(!mWindowListener);
|
||||
}
|
||||
|
||||
bool SourceListener::CapturingVideo() const {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return Activated() && mVideoDeviceState && !mVideoDeviceState->mStopped &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче