Bug 1369108 - 1. Introduce optional device permission step; r=jesup

Right before `MediaManager::EnumerateRawDevices` posts its enumeration
task to the background thread, add the option to send out a
"getUserMedia:ask-device-permission" notification, whose purpose is to
give frontend UI a chance to ask for device permissions (e.g. permission
to enumerate cameras on Android).

The subject parameter of the notification is an `nsIRunnable` task,
which is passed back to `MediaManager`, after receiving permission,
through the `getUserMedia:got-device-permission` notification. The
notification listener then posts the task and enumeration proceeds as
before.

MozReview-Commit-ID: IhRXTdIplvN
This commit is contained in:
Jim Chen 2017-06-02 16:11:53 -04:00
Родитель bb8b90d00e
Коммит 378c61c98f
1 изменённых файлов: 33 добавлений и 4 удалений

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

@ -1699,9 +1699,9 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
} }
} }
MediaManager::PostTask(NewTaskFrom([id, aWindowId, audioLoopDev, RefPtr<Runnable> task = NewTaskFrom([id, aWindowId, audioLoopDev,
videoLoopDev, aVideoType, videoLoopDev, aVideoType,
aAudioType, aFake]() mutable { aAudioType, aFake]() mutable {
// Only enumerate what's asked for, and only fake cams and mics. // Only enumerate what's asked for, and only fake cams and mics.
bool hasVideo = aVideoType != MediaSourceEnum::Other; bool hasVideo = aVideoType != MediaSourceEnum::Other;
bool hasAudio = aAudioType != MediaSourceEnum::Other; bool hasAudio = aAudioType != MediaSourceEnum::Other;
@ -1748,7 +1748,28 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
} }
return NS_OK; return NS_OK;
})); }));
})); });
if (!aFake &&
(aVideoType == MediaSourceEnum::Camera ||
aAudioType == MediaSourceEnum::Microphone) &&
Preferences::GetBool("media.navigator.permission.device", false)) {
// Need to ask permission to retrieve list of all devices;
// notify frontend observer and wait for callback notification to post task.
const char16_t* const type =
(aVideoType != MediaSourceEnum::Camera) ? u"audio" :
(aAudioType != MediaSourceEnum::Microphone) ? u"video" :
u"all";
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
obs->NotifyObservers(static_cast<nsIRunnable*>(task),
"getUserMedia:ask-device-permission",
type);
} else {
// Don't need to ask permission to retrieve list of all devices;
// post the retrieval task immediately.
MediaManager::PostTask(task.forget());
}
return p.forget(); return p.forget();
} }
@ -1841,6 +1862,7 @@ MediaManager::Get() {
nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs) { if (obs) {
obs->AddObserver(sSingleton, "last-pb-context-exited", false); obs->AddObserver(sSingleton, "last-pb-context-exited", false);
obs->AddObserver(sSingleton, "getUserMedia:got-device-permission", false);
obs->AddObserver(sSingleton, "getUserMedia:privileged:allow", false); obs->AddObserver(sSingleton, "getUserMedia:privileged:allow", false);
obs->AddObserver(sSingleton, "getUserMedia:response:allow", false); obs->AddObserver(sSingleton, "getUserMedia:response:allow", false);
obs->AddObserver(sSingleton, "getUserMedia:response:deny", false); obs->AddObserver(sSingleton, "getUserMedia:response:deny", false);
@ -3019,6 +3041,13 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
// Clear memory of private-browsing-specific deviceIds. Fire and forget. // Clear memory of private-browsing-specific deviceIds. Fire and forget.
media::SanitizeOriginKeys(0, true); media::SanitizeOriginKeys(0, true);
return NS_OK; return NS_OK;
} else if (!strcmp(aTopic, "getUserMedia:got-device-permission")) {
MOZ_ASSERT(aSubject);
nsCOMPtr<nsIRunnable> task = do_QueryInterface(aSubject);
MediaManager::PostTask(NewTaskFrom([task] {
task->Run();
}));
return NS_OK;
} else if (!strcmp(aTopic, "getUserMedia:privileged:allow") || } else if (!strcmp(aTopic, "getUserMedia:privileged:allow") ||
!strcmp(aTopic, "getUserMedia:response:allow")) { !strcmp(aTopic, "getUserMedia:response:allow")) {
nsString key(aData); nsString key(aData);