Bug 1364038 - Call SourceListener::StopTrack when the coresponding external device is disconnected. r=jib

MozReview-Commit-ID: EfpmXBJf7PP

--HG--
extra : rebase_source : 328b146ba3531f10a36147f820e84f4d8402ff8a
This commit is contained in:
Munro Mengjue Chiang 2017-07-27 16:51:24 +08:00
Родитель dfb597110e
Коммит dc857a8098
2 изменённых файлов: 92 добавлений и 3 удалений

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

@ -530,6 +530,8 @@ public:
void StopSharing();
void StopRawID(const nsString& removedDeviceID);
/**
* Called by one of our SourceListeners when one of its tracks has stopped.
* Schedules an event for the next stable state to update chrome.
@ -1728,6 +1730,8 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
if ((!fakeCams && hasVideo) || (!fakeMics && hasAudio)) {
RefPtr<MediaManager> manager = MediaManager_GetInstance();
realBackend = manager->GetBackend(aWindowId);
// We need to listen to this event even JS didn't listen to it.
realBackend->AddDeviceChangeCallback(manager);
}
auto result = MakeUnique<SourceSet>();
@ -2037,7 +2041,6 @@ int MediaManager::AddDeviceChangeCallback(DeviceChangeCallback* aCallback)
bool fakeDeviceChangeEventOn = mPrefs.mFakeDeviceChangeEventOn;
MediaManager::PostTask(NewTaskFrom([fakeDeviceChangeEventOn]() {
RefPtr<MediaManager> manager = MediaManager_GetInstance();
manager->GetBackend(0)->AddDeviceChangeCallback(manager);
if (fakeDeviceChangeEventOn)
manager->GetBackend(0)->SetFakeDeviceChangeEvents();
}));
@ -2045,11 +2048,61 @@ int MediaManager::AddDeviceChangeCallback(DeviceChangeCallback* aCallback)
return DeviceChangeCallback::AddDeviceChangeCallback(aCallback);
}
static void
StopRawIDCallback(MediaManager *aThis,
uint64_t aWindowID,
GetUserMediaWindowListener *aListener,
void *aData)
{
if (!aListener || !aData) {
return;
}
nsString* removedDeviceID = static_cast<nsString*>(aData);
aListener->StopRawID(*removedDeviceID);
}
void MediaManager::OnDeviceChange() {
RefPtr<MediaManager> self(this);
NS_DispatchToMainThread(media::NewRunnableFrom([self,this]() mutable {
NS_DispatchToMainThread(media::NewRunnableFrom([self]() mutable {
MOZ_ASSERT(NS_IsMainThread());
DeviceChangeCallback::OnDeviceChange();
self->DeviceChangeCallback::OnDeviceChange();
// On some Windows machine, if we call EnumertaeRawDevices immediately after receiving
// devicechange event, sometimes we would get outdated devices list.
PR_Sleep(PR_MillisecondsToInterval(100));
RefPtr<PledgeSourceSet> p = self->EnumerateRawDevices(0, MediaSourceEnum::Camera, MediaSourceEnum::Microphone, false);
p->Then([self](SourceSet*& aDevices) mutable {
UniquePtr<SourceSet> devices(aDevices);
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& id : self->mDeviceIDs) {
if (!deviceIDs.Contains(id)) {
// Stop the coresponding SourceListener
nsGlobalWindow::WindowByIdTable* windowsById = nsGlobalWindow::GetWindowsTable();
if (windowsById) {
for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
nsGlobalWindow* window = iter.Data();
if (window->IsInnerWindow()) {
self->IterateWindowListeners(window->AsInner(), StopRawIDCallback, &id);
}
}
}
}
}
self->mDeviceIDs = deviceIDs;
}, [](MediaStreamError*& reason) {});
return NS_OK;
}));
}
@ -2658,6 +2711,17 @@ MediaManager::EnumerateDevicesImpl(uint64_t aWindowId,
if (!mgr) {
return NS_OK;
}
mgr->mDeviceIDs.Clear();
for (auto& device : *devices) {
nsString id;
device->GetId(id);
id.ReplaceSubstring(NS_LITERAL_STRING("default: "), NS_LITERAL_STRING(""));
if (!mgr->mDeviceIDs.Contains(id)) {
mgr->mDeviceIDs.AppendElement(id);
}
}
RefPtr<PledgeSourceSet> p = mgr->mOutstandingPledges.Remove(id);
if (!p || !mgr->IsWindowStillActive(aWindowId)) {
return NS_OK;
@ -2985,6 +3049,7 @@ MediaManager::Shutdown()
mActiveCallbacks.Clear();
mCallIds.Clear();
mPendingGUMRequest.Clear();
mDeviceIDs.Clear();
#ifdef MOZ_WEBRTC
StopWebRtcLog();
#endif
@ -3975,6 +4040,29 @@ GetUserMediaWindowListener::StopSharing()
}
}
void
GetUserMediaWindowListener::StopRawID(const nsString& removedDeviceID)
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread");
for (auto& source : mActiveListeners) {
if (source->GetAudioDevice()) {
nsString id;
source->GetAudioDevice()->GetRawId(id);
if (removedDeviceID.Equals(id)) {
source->Stop();
}
}
if (source->GetVideoDevice()) {
nsString id;
source->GetVideoDevice()->GetRawId(id);
if (removedDeviceID.Equals(id)) {
source->Stop();
}
}
}
}
void
GetUserMediaWindowListener::NotifySourceTrackStopped()
{

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

@ -334,6 +334,7 @@ private:
media::CoatCheck<PledgeSourceSet> mOutstandingPledges;
media::CoatCheck<PledgeChar> mOutstandingCharPledges;
media::CoatCheck<PledgeVoid> mOutstandingVoidPledges;
nsTArray<nsString> mDeviceIDs;
public:
media::CoatCheck<media::Pledge<nsCString>> mGetPrincipalKeyPledges;
RefPtr<media::Parent<media::NonE10s>> mNonE10sParent;