mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 11:58:55 +00:00
Bug 1908056 - Add media.devices.enumerate.legacy.allowlist exception for slack. r=dbaker
Differential Revision: https://phabricator.services.mozilla.com/D224367
This commit is contained in:
parent
4921bad37a
commit
0ea5919a4d
@ -231,6 +231,21 @@ void MediaDevices::MaybeResumeDeviceExposure() {
|
||||
mHaveUnprocessedDeviceListChange = false;
|
||||
}
|
||||
|
||||
static bool IsLegacyMode(nsPIDOMWindowInner* window) {
|
||||
if (StaticPrefs::media_devices_enumerate_legacy_enabled()) {
|
||||
return true;
|
||||
}
|
||||
if (window->GetDocumentURI()) {
|
||||
nsAutoCString host;
|
||||
window->GetDocumentURI()->GetAsciiHost(host);
|
||||
if (media::HostnameInPref("media.devices.enumerate.legacy.allowlist",
|
||||
host)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<MediaDeviceSetRefCnt> MediaDevices::FilterExposedDevices(
|
||||
const MediaDeviceSet& aDevices) const {
|
||||
nsPIDOMWindowInner* window = GetOwnerWindow();
|
||||
@ -250,7 +265,7 @@ RefPtr<MediaDeviceSetRefCnt> MediaDevices::FilterExposedDevices(
|
||||
!Preferences::GetBool("media.setsinkid.enabled") ||
|
||||
!FeaturePolicyUtils::IsFeatureAllowed(doc, u"speaker-selection"_ns);
|
||||
|
||||
bool legacy = StaticPrefs::media_devices_enumerate_legacy_enabled();
|
||||
bool legacy = IsLegacyMode(window);
|
||||
bool outputIsDefault = true; // First output is the default.
|
||||
bool haveDefaultOutput = false;
|
||||
nsTHashSet<nsString> exposedMicrophoneGroupIds;
|
||||
@ -467,7 +482,7 @@ void MediaDevices::ResolveEnumerateDevicesPromise(
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = GetOwnerWindow();
|
||||
auto windowId = window->WindowID();
|
||||
nsTArray<RefPtr<MediaDeviceInfo>> infos;
|
||||
bool legacy = StaticPrefs::media_devices_enumerate_legacy_enabled();
|
||||
bool legacy = IsLegacyMode(window);
|
||||
bool capturePermitted =
|
||||
legacy &&
|
||||
MediaManager::Get()->IsActivelyCapturingOrHasAPermission(windowId);
|
||||
|
@ -7,10 +7,64 @@
|
||||
#include "MediaUtils.h"
|
||||
|
||||
#include "mozilla/AppShutdown.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
namespace mozilla::media {
|
||||
|
||||
bool HostnameInPref(const char* aPref, const nsCString& aHostName) {
|
||||
auto HostInDomain = [](const nsCString& aHost, const nsCString& aPattern) {
|
||||
int32_t patternOffset = 0;
|
||||
int32_t hostOffset = 0;
|
||||
|
||||
// Act on '*.' wildcard in the left-most position in a domain pattern.
|
||||
if (StringBeginsWith(aPattern, nsCString("*."))) {
|
||||
patternOffset = 2;
|
||||
|
||||
// Ignore the lowest level sub-domain for the hostname.
|
||||
hostOffset = aHost.FindChar('.') + 1;
|
||||
|
||||
if (hostOffset <= 1) {
|
||||
// Reject a match between a wildcard and a TLD or '.foo' form.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsDependentCString hostRoot(aHost, hostOffset);
|
||||
return hostRoot.EqualsIgnoreCase(aPattern.BeginReading() + patternOffset);
|
||||
};
|
||||
|
||||
nsCString domainList;
|
||||
nsresult rv = Preferences::GetCString(aPref, domainList);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
domainList.StripWhitespace();
|
||||
|
||||
if (domainList.IsEmpty() || aHostName.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test each domain name in the comma separated list
|
||||
// after converting from UTF8 to ASCII. Each domain
|
||||
// must match exactly or have a single leading '*.' wildcard.
|
||||
for (const nsACString& each : domainList.Split(',')) {
|
||||
nsCString domainPattern;
|
||||
rv = NS_DomainToASCIIAllowAnyGlyphfulASCII(each, domainPattern);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (HostInDomain(aHostName, domainPattern)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("Failed to convert UTF-8 host to ASCII");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAsyncShutdownClient> GetShutdownBarrier() {
|
||||
nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdownService();
|
||||
if (!svc) {
|
||||
|
@ -28,6 +28,12 @@ class nsIEventTarget;
|
||||
|
||||
namespace mozilla::media {
|
||||
|
||||
/* Utility function, given a string pref and an URI, returns whether or not
|
||||
* the URI occurs in the pref. Wildcards are supported (e.g. *.example.com)
|
||||
* and multiple hostnames can be present, separated by commas.
|
||||
*/
|
||||
bool HostnameInPref(const char* aPrefList, const nsCString& aHostName);
|
||||
|
||||
/* media::NewRunnableFrom() - Create a Runnable from a lambda.
|
||||
*
|
||||
* Passing variables (closures) to an async function is clunky with Runnable:
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/StaticPrefs_media.h"
|
||||
#include "mozilla/media/MediaUtils.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
// We need to undef the MS macro for Document::CreateEvent
|
||||
@ -396,9 +397,9 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal)
|
||||
mEffectiveTLDPlus1);
|
||||
}
|
||||
|
||||
mRtxIsAllowed = !HostnameInPref(
|
||||
mRtxIsAllowed = !media::HostnameInPref(
|
||||
"media.peerconnection.video.use_rtx.blocklist", mHostname);
|
||||
mDuplicateFingerprintQuirk = HostnameInPref(
|
||||
mDuplicateFingerprintQuirk = media::HostnameInPref(
|
||||
"media.peerconnection.sdp.quirk.duplicate_fingerprint.allowlist",
|
||||
mHostname);
|
||||
}
|
||||
@ -2160,60 +2161,6 @@ void PeerConnectionImpl::DumpPacket_m(size_t level, dom::mozPacketDumpType type,
|
||||
mPCObserver->OnPacket(level, type, sending, arrayBuffer, jrv);
|
||||
}
|
||||
|
||||
bool PeerConnectionImpl::HostnameInPref(const char* aPref,
|
||||
const nsCString& aHostName) {
|
||||
auto HostInDomain = [](const nsCString& aHost, const nsCString& aPattern) {
|
||||
int32_t patternOffset = 0;
|
||||
int32_t hostOffset = 0;
|
||||
|
||||
// Act on '*.' wildcard in the left-most position in a domain pattern.
|
||||
if (StringBeginsWith(aPattern, nsCString("*."))) {
|
||||
patternOffset = 2;
|
||||
|
||||
// Ignore the lowest level sub-domain for the hostname.
|
||||
hostOffset = aHost.FindChar('.') + 1;
|
||||
|
||||
if (hostOffset <= 1) {
|
||||
// Reject a match between a wildcard and a TLD or '.foo' form.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsDependentCString hostRoot(aHost, hostOffset);
|
||||
return hostRoot.EqualsIgnoreCase(aPattern.BeginReading() + patternOffset);
|
||||
};
|
||||
|
||||
nsCString domainList;
|
||||
nsresult rv = Preferences::GetCString(aPref, domainList);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
domainList.StripWhitespace();
|
||||
|
||||
if (domainList.IsEmpty() || aHostName.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test each domain name in the comma separated list
|
||||
// after converting from UTF8 to ASCII. Each domain
|
||||
// must match exactly or have a single leading '*.' wildcard.
|
||||
for (const nsACString& each : domainList.Split(',')) {
|
||||
nsCString domainPattern;
|
||||
rv = NS_DomainToASCIIAllowAnyGlyphfulASCII(each, domainPattern);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (HostInDomain(aHostName, domainPattern)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("Failed to convert UTF-8 host to ASCII");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult PeerConnectionImpl::EnablePacketDump(unsigned long level,
|
||||
dom::mozPacketDumpType type,
|
||||
bool sending) {
|
||||
@ -4452,7 +4399,7 @@ bool PeerConnectionImpl::GetPrefObfuscateHostAddresses() const {
|
||||
"media.peerconnection.ice.obfuscate_host_addresses", false);
|
||||
obfuscate_host_addresses &=
|
||||
!MediaManager::Get()->IsActivelyCapturingOrHasAPermission(winId);
|
||||
obfuscate_host_addresses &= !PeerConnectionImpl::HostnameInPref(
|
||||
obfuscate_host_addresses &= !media::HostnameInPref(
|
||||
"media.peerconnection.ice.obfuscate_host_addresses.blocklist", mHostname);
|
||||
obfuscate_host_addresses &= XRE_IsContentProcess();
|
||||
|
||||
|
@ -534,11 +534,6 @@ class PeerConnectionImpl final
|
||||
return mTimestampMaker;
|
||||
}
|
||||
|
||||
// Utility function, given a string pref and an URI, returns whether or not
|
||||
// the URI occurs in the pref. Wildcards are supported (e.g. *.example.com)
|
||||
// and multiple hostnames can be present, separated by commas.
|
||||
static bool HostnameInPref(const char* aPrefList, const nsCString& aHostName);
|
||||
|
||||
void StampTimecard(const char* aEvent);
|
||||
|
||||
bool RelayOnly() const {
|
||||
|
@ -47,12 +47,9 @@ function validateDevice({kind, label, deviceId, groupId}) {
|
||||
isnot(groupId, "", "groupId must be present.");
|
||||
}
|
||||
|
||||
runTest(async () => {
|
||||
await pushPrefs(["media.navigator.streams.fake", true],
|
||||
["media.devices.enumerate.legacy.enabled", true]);
|
||||
|
||||
// Validate enumerated devices before gUM (legacy).
|
||||
// Validate enumerated devices before gUM (legacy).
|
||||
|
||||
async function testLegacyEnumerateDevices() {
|
||||
let devices = await navigator.mediaDevices.enumerateDevices();
|
||||
ok(devices.length, "At least one device found");
|
||||
const jsoned = JSON.parse(JSON.stringify(devices));
|
||||
@ -140,7 +137,17 @@ runTest(async () => {
|
||||
["media.video_loopback_dev", "none"]);
|
||||
devices = await navigator.mediaDevices.enumerateDevices();
|
||||
is(devices.length, 0, "No devices");
|
||||
}
|
||||
|
||||
runTest(async () => {
|
||||
await withPrefs([["media.navigator.streams.fake", true],
|
||||
["media.devices.enumerate.legacy.allowlist", "example.com,*.example.com"]],
|
||||
testLegacyEnumerateDevices);
|
||||
await withPrefs([["media.navigator.streams.fake", true],
|
||||
["media.devices.enumerate.legacy.enabled", true]],
|
||||
testLegacyEnumerateDevices);
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
@ -11491,6 +11491,14 @@
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Turns on legacy (non-spec) exposure of camera and microphone information
|
||||
# from enumerateDevices and devicechange ahead of successful getUserMedia
|
||||
# calls only for certain domains (ignored if above pref is true).
|
||||
- name: media.devices.enumerate.legacy.allowlist
|
||||
type: String
|
||||
value: "slack.com,*.slack.com"
|
||||
mirror: never
|
||||
|
||||
# WebRTC prefs follow
|
||||
|
||||
# Enables auto refresh of peerconnection stats by default
|
||||
|
Loading…
x
Reference in New Issue
Block a user