зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1811836: Move devicechange rfp check from OnDeviceChange to MaybeResumeDeviceExposure where we always have window. r=tjr
Differential Revision: https://phabricator.services.mozilla.com/D222291
This commit is contained in:
Родитель
b1b95fe1bc
Коммит
6bf386cd12
|
@ -200,15 +200,18 @@ void MediaDevices::MaybeResumeDeviceExposure() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
bool shouldResistFingerprinting =
|
||||
window->AsGlobal()->ShouldResistFingerprinting(RFPTarget::MediaDevices);
|
||||
MediaManager::Get()->GetPhysicalDevices()->Then(
|
||||
GetCurrentSerialEventTarget(), __func__,
|
||||
[self = RefPtr(this), this,
|
||||
haveDeviceListChange = mHaveUnprocessedDeviceListChange,
|
||||
enumerateDevicesPromises = std::move(mPendingEnumerateDevicesPromises)](
|
||||
enumerateDevicesPromises = std::move(mPendingEnumerateDevicesPromises),
|
||||
shouldResistFingerprinting](
|
||||
RefPtr<const MediaDeviceSetRefCnt> aAllDevices) mutable {
|
||||
RefPtr<MediaDeviceSetRefCnt> exposedDevices =
|
||||
FilterExposedDevices(*aAllDevices);
|
||||
if (haveDeviceListChange) {
|
||||
if (haveDeviceListChange && !shouldResistFingerprinting) {
|
||||
if (ShouldQueueDeviceChange(*exposedDevices)) {
|
||||
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
|
||||
"devicechange", [self = RefPtr(this), this] {
|
||||
|
@ -762,28 +765,6 @@ void MediaDevices::OnDeviceChange() {
|
|||
return;
|
||||
}
|
||||
|
||||
// Do not fire event to content script when
|
||||
// privacy.resistFingerprinting is true.
|
||||
|
||||
if (nsContentUtils::ShouldResistFingerprinting(
|
||||
"Guarding the more expensive RFP check with a simple one",
|
||||
RFPTarget::MediaDevices)) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = GetOwnerWindow();
|
||||
auto* wrapper = GetWrapper();
|
||||
if (!window && wrapper) {
|
||||
nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(wrapper);
|
||||
window = do_QueryInterface(global);
|
||||
}
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsGlobalWindowInner::Cast(window)->ShouldResistFingerprinting(
|
||||
RFPTarget::MediaDevices)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mHaveUnprocessedDeviceListChange = true;
|
||||
MaybeResumeDeviceExposure();
|
||||
}
|
||||
|
|
|
@ -83,3 +83,6 @@ skip-if = ["os != 'linux'"] # the only platform with real devices
|
|||
["test_setSinkId_preMutedElement.html"]
|
||||
|
||||
["test_unfocused_pref.html"]
|
||||
|
||||
["test_ondevicechange_resistfingerprinting.html"]
|
||||
run-sequentially = "sets prefs that may disrupt other tests"
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
|
||||
createHTML({
|
||||
title: "ondevicechange test with privacy.resistFingerprinting",
|
||||
bug: "1811836",
|
||||
});
|
||||
|
||||
async function resolveOnEvent(target, name) {
|
||||
return new Promise(r =>
|
||||
target.addEventListener(name, r, { once: true })
|
||||
);
|
||||
}
|
||||
let eventCount = 0;
|
||||
async function triggerVideoDevicechange() {
|
||||
++eventCount;
|
||||
// "media.getusermedia.fake-camera-name" specifies the name of the single
|
||||
// fake video camera.
|
||||
// Changing the pref imitates replacing one device with another.
|
||||
return pushPrefs([
|
||||
"media.getusermedia.fake-camera-name",
|
||||
`devicechange ${eventCount}`,
|
||||
]);
|
||||
}
|
||||
|
||||
runTest(async () => {
|
||||
const basePrefs = [
|
||||
// Use the fake video backend to trigger devicechange events.
|
||||
["media.navigator.streams.fake", true],
|
||||
// Loopback would override fake.
|
||||
["media.video_loopback_dev", ""],
|
||||
// Make fake devices count as real, permission-wise, or devicechange
|
||||
// events won't be exposed
|
||||
["media.navigator.permission.fake", true],
|
||||
// For gUM.
|
||||
["media.navigator.permission.disabled", true],
|
||||
];
|
||||
|
||||
await withPrefs(
|
||||
[
|
||||
...basePrefs,
|
||||
// Enable privacy.resistFingerprinting to test the prevention of
|
||||
// device list changes.
|
||||
["privacy.resistFingerprinting", true],
|
||||
],
|
||||
async () => {
|
||||
const topDevices = navigator.mediaDevices;
|
||||
const topEventPromise1 = resolveOnEvent(topDevices, "devicechange");
|
||||
(await topDevices.getUserMedia({ video: true }))
|
||||
.getTracks()[0]
|
||||
.stop();
|
||||
|
||||
await triggerVideoDevicechange(); // Pop pref list after this.
|
||||
|
||||
const racer = {};
|
||||
is(
|
||||
await Promise.race([topEventPromise1, racer]),
|
||||
racer,
|
||||
"devicechange event is NOT fired in top window for replaced device when " +
|
||||
"privacy.resistFingerprinting is enabled"
|
||||
);
|
||||
await SpecialPowers.popPrefEnv();
|
||||
}
|
||||
);
|
||||
|
||||
await withPrefs(
|
||||
[
|
||||
...basePrefs,
|
||||
// Disable privacy.resistFingerprinting to test the exposure of device list
|
||||
// changes.
|
||||
["privacy.resistFingerprinting", false],
|
||||
],
|
||||
async () => {
|
||||
const topDevices = navigator.mediaDevices;
|
||||
const topEventPromise2 = resolveOnEvent(topDevices, "devicechange");
|
||||
|
||||
await triggerVideoDevicechange();
|
||||
|
||||
await topEventPromise2;
|
||||
ok(
|
||||
true,
|
||||
"devicechange event is fired in top window for replaced device when " +
|
||||
"privacy.resistFingerprinting is disabled"
|
||||
);
|
||||
await SpecialPowers.popPrefEnv();
|
||||
}
|
||||
);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче