mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1720643 perform getUserMedia Permissions Policy checks even when "media.navigator.permission.disabled" is set r=jib
"media.getusermedia.microphone.deny" and "media.getusermedia.camera.deny" now override "media.navigator.permission.disabled". User permission checks are removed because they are repeated in the app. Differential Revision: https://phabricator.services.mozilla.com/D120065
This commit is contained in:
parent
17188fda8e
commit
893f19930e
@ -520,17 +520,15 @@ var gTests = [
|
||||
} else {
|
||||
let expectedMessage = aExpectStream ? "ok" : permissionError;
|
||||
|
||||
let observerPromises = [];
|
||||
let observerPromises = [expectObserverCalled("getUserMedia:request")];
|
||||
if (expectedMessage == "ok") {
|
||||
observerPromises.push(expectObserverCalled("getUserMedia:request"));
|
||||
observerPromises.push(
|
||||
expectObserverCalled("getUserMedia:response:allow")
|
||||
);
|
||||
observerPromises.push(
|
||||
expectObserverCalled("getUserMedia:response:allow"),
|
||||
expectObserverCalled("recording-device-events")
|
||||
);
|
||||
} else {
|
||||
observerPromises.push(
|
||||
expectObserverCalled("getUserMedia:response:deny"),
|
||||
expectObserverCalled("recording-window-ended")
|
||||
);
|
||||
}
|
||||
|
@ -16,24 +16,28 @@ var gTests = [
|
||||
Services.prefs.setIntPref(CAMERA_PREF, SitePermissions.BLOCK);
|
||||
|
||||
// Requesting audio+video shouldn't work.
|
||||
let observerPromise = expectObserverCalled("recording-window-ended");
|
||||
let promise = promiseMessage(permissionError);
|
||||
await promiseRequestDevice(true, true);
|
||||
await promise;
|
||||
await observerPromise;
|
||||
await Promise.all([
|
||||
expectObserverCalled("getUserMedia:request"),
|
||||
expectObserverCalled("getUserMedia:response:deny"),
|
||||
expectObserverCalled("recording-window-ended"),
|
||||
promiseMessage(permissionError),
|
||||
promiseRequestDevice(true, true),
|
||||
]);
|
||||
await checkNotSharing();
|
||||
|
||||
// Requesting only video shouldn't work.
|
||||
observerPromise = expectObserverCalled("recording-window-ended");
|
||||
promise = promiseMessage(permissionError);
|
||||
await promiseRequestDevice(false, true);
|
||||
await promise;
|
||||
await observerPromise;
|
||||
await Promise.all([
|
||||
expectObserverCalled("getUserMedia:request"),
|
||||
expectObserverCalled("getUserMedia:response:deny"),
|
||||
expectObserverCalled("recording-window-ended"),
|
||||
promiseMessage(permissionError),
|
||||
promiseRequestDevice(false, true),
|
||||
]);
|
||||
await checkNotSharing();
|
||||
|
||||
// Requesting audio should work.
|
||||
observerPromise = expectObserverCalled("getUserMedia:request");
|
||||
promise = promisePopupNotificationShown("webRTC-shareDevices");
|
||||
const observerPromise = expectObserverCalled("getUserMedia:request");
|
||||
const promise = promisePopupNotificationShown("webRTC-shareDevices");
|
||||
await promiseRequestDevice(true);
|
||||
await promise;
|
||||
await observerPromise;
|
||||
@ -110,24 +114,27 @@ var gTests = [
|
||||
Services.prefs.setIntPref(MICROPHONE_PREF, SitePermissions.BLOCK);
|
||||
|
||||
// Requesting audio+video shouldn't work.
|
||||
let observerPromise = expectObserverCalled("recording-window-ended");
|
||||
let promise = promiseMessage(permissionError);
|
||||
await promiseRequestDevice(true, true);
|
||||
await promise;
|
||||
await observerPromise;
|
||||
await Promise.all([
|
||||
expectObserverCalled("getUserMedia:request"),
|
||||
expectObserverCalled("getUserMedia:response:deny"),
|
||||
expectObserverCalled("recording-window-ended"),
|
||||
promiseMessage(permissionError),
|
||||
promiseRequestDevice(true, true),
|
||||
]);
|
||||
await checkNotSharing();
|
||||
|
||||
// Requesting only audio shouldn't work.
|
||||
observerPromise = expectObserverCalled("recording-window-ended");
|
||||
promise = promiseMessage(permissionError);
|
||||
await promiseRequestDevice(true);
|
||||
await promise;
|
||||
await observerPromise;
|
||||
await checkNotSharing();
|
||||
await Promise.all([
|
||||
expectObserverCalled("getUserMedia:request"),
|
||||
expectObserverCalled("getUserMedia:response:deny"),
|
||||
expectObserverCalled("recording-window-ended"),
|
||||
promiseMessage(permissionError),
|
||||
promiseRequestDevice(true),
|
||||
]);
|
||||
|
||||
// Requesting video should work.
|
||||
observerPromise = expectObserverCalled("getUserMedia:request");
|
||||
promise = promisePopupNotificationShown("webRTC-shareDevices");
|
||||
const observerPromise = expectObserverCalled("getUserMedia:request");
|
||||
const promise = promisePopupNotificationShown("webRTC-shareDevices");
|
||||
await promiseRequestDevice(false, true);
|
||||
await promise;
|
||||
await observerPromise;
|
||||
|
@ -366,13 +366,20 @@ var gTests = [
|
||||
|
||||
await closeStream(false, aIframeId);
|
||||
} else if (aExpect == PromptResult.DENY) {
|
||||
const observerPromise = expectObserverCalled(
|
||||
"recording-window-ended"
|
||||
const promises = [];
|
||||
// frame3 disallows by feature Permissions Policy before request.
|
||||
if (aIframeId != "frame3") {
|
||||
promises.push(
|
||||
expectObserverCalled("getUserMedia:request"),
|
||||
expectObserverCalled("getUserMedia:response:deny")
|
||||
);
|
||||
}
|
||||
promises.push(
|
||||
expectObserverCalled("recording-window-ended"),
|
||||
promiseMessage(permissionError),
|
||||
promiseRequestDevice(audio, video, aIframeId, screen)
|
||||
);
|
||||
const promise = promiseMessage(permissionError);
|
||||
await promiseRequestDevice(audio, video, aIframeId, screen);
|
||||
await promise;
|
||||
await observerPromise;
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
PermissionTestUtils.remove(uri, aRequestType);
|
||||
|
@ -757,11 +757,13 @@ var gTests = [
|
||||
);
|
||||
|
||||
// Request screensharing again, expect an immediate failure.
|
||||
observerPromise = expectObserverCalled("recording-window-ended");
|
||||
promise = promiseMessage(permissionError);
|
||||
await promiseRequestDevice(false, true, null, "screen");
|
||||
await promise;
|
||||
await observerPromise;
|
||||
await Promise.all([
|
||||
expectObserverCalled("getUserMedia:request"),
|
||||
expectObserverCalled("getUserMedia:response:deny"),
|
||||
expectObserverCalled("recording-window-ended"),
|
||||
promiseMessage(permissionError),
|
||||
promiseRequestDevice(false, true, null, "screen"),
|
||||
]);
|
||||
|
||||
// Now set the permission to allow and expect a prompt.
|
||||
SitePermissions.setForPrincipal(
|
||||
|
@ -2640,45 +2640,32 @@ RefPtr<MediaManager::StreamPromise> MediaManager::GetUserMedia(
|
||||
auto placeholderListener = MakeRefPtr<DeviceListener>();
|
||||
windowListener->Register(placeholderListener);
|
||||
|
||||
if (!privileged) {
|
||||
// Check if this site has had persistent permissions denied.
|
||||
RefPtr<PermissionDelegateHandler> permDelegate =
|
||||
doc->GetPermissionDelegateHandler();
|
||||
MOZ_RELEASE_ASSERT(permDelegate);
|
||||
|
||||
uint32_t audioPerm = nsIPermissionManager::UNKNOWN_ACTION;
|
||||
{ // Check Permissions Policy. Reject if a requested feature is disabled.
|
||||
bool disabled = !IsOn(c.mAudio) && !IsOn(c.mVideo);
|
||||
if (IsOn(c.mAudio)) {
|
||||
if (audioType == MediaSourceEnum::Microphone) {
|
||||
if (Preferences::GetBool("media.getusermedia.microphone.deny", false)) {
|
||||
audioPerm = nsIPermissionManager::DENY_ACTION;
|
||||
} else {
|
||||
rv = permDelegate->GetPermission("microphone"_ns, &audioPerm, true);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (Preferences::GetBool("media.getusermedia.microphone.deny", false) ||
|
||||
!FeaturePolicyUtils::IsFeatureAllowed(doc, u"microphone"_ns)) {
|
||||
disabled = true;
|
||||
}
|
||||
} else {
|
||||
rv = permDelegate->GetPermission("screen"_ns, &audioPerm, true);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
} else if (!FeaturePolicyUtils::IsFeatureAllowed(doc,
|
||||
u"display-capture"_ns)) {
|
||||
disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t videoPerm = nsIPermissionManager::UNKNOWN_ACTION;
|
||||
if (IsOn(c.mVideo)) {
|
||||
if (videoType == MediaSourceEnum::Camera) {
|
||||
if (Preferences::GetBool("media.getusermedia.camera.deny", false)) {
|
||||
videoPerm = nsIPermissionManager::DENY_ACTION;
|
||||
} else {
|
||||
rv = permDelegate->GetPermission("camera"_ns, &videoPerm, true);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (Preferences::GetBool("media.getusermedia.camera.deny", false) ||
|
||||
!FeaturePolicyUtils::IsFeatureAllowed(doc, u"camera"_ns)) {
|
||||
disabled = true;
|
||||
}
|
||||
} else {
|
||||
rv = permDelegate->GetPermission("screen"_ns, &videoPerm, true);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
} else if (!FeaturePolicyUtils::IsFeatureAllowed(doc,
|
||||
u"display-capture"_ns)) {
|
||||
disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!IsOn(c.mAudio) && !IsOn(c.mVideo)) ||
|
||||
(IsOn(c.mAudio) && audioPerm == nsIPermissionManager::DENY_ACTION) ||
|
||||
(IsOn(c.mVideo) && videoPerm == nsIPermissionManager::DENY_ACTION)) {
|
||||
if (disabled) {
|
||||
placeholderListener->Stop();
|
||||
return StreamPromise::CreateAndReject(
|
||||
MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError),
|
||||
|
@ -59,9 +59,17 @@ runTest(async () => {
|
||||
const src = origin + path;
|
||||
is(await iframeGum({ src, sandbox: "allow-scripts" }),
|
||||
"NotAllowedError", "gUM fails in sandboxed iframe " + origin);
|
||||
is(await iframeGum({ src, sandbox: "allow-scripts allow-same-origin" }),
|
||||
"success", "gUM works in regular iframe" + origin);
|
||||
}
|
||||
is(await iframeGum({
|
||||
src: path,
|
||||
sandbox: "allow-scripts allow-same-origin",
|
||||
}),
|
||||
"success", "gUM works in regular same-origin iframe");
|
||||
is(await iframeGum({
|
||||
src: `https://test1.example.com${path}`,
|
||||
sandbox: "allow-scripts allow-same-origin",
|
||||
}),
|
||||
"NotAllowedError", "gUM fails in regular cross-origin iframe");
|
||||
|
||||
// Test gUM in sandboxed vs regular srcdoc iframe
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
[MediaStream-default-feature-policy.https.sub.html]
|
||||
[Default "microphone" feature policy ["self"\] disallows cross-origin iframes.]
|
||||
expected: FAIL
|
||||
|
||||
[Default "camera" feature policy ["self"\] disallows cross-origin iframes.]
|
||||
expected: FAIL
|
||||
|
||||
[Default "camera;microphone" feature policy ["self"\] disallows cross-origin iframes.]
|
||||
expected: FAIL
|
||||
|
||||
[Feature policy "microphone" can be enabled in cross-origin iframes using "allow" attribute.]
|
||||
expected: FAIL
|
||||
|
||||
[Feature policy "camera" can be enabled in cross-origin iframes using "allow" attribute.]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[MediaStream-default-feature-policy.https.html]
|
||||
[Default "microphone" feature policy ["self"\] disallows cross-origin iframes.]
|
||||
expected: FAIL
|
||||
|
||||
[Default "camera" feature policy ["self"\] disallows cross-origin iframes.]
|
||||
expected: FAIL
|
||||
|
||||
[Default "camera;microphone" feature policy ["self"\] disallows cross-origin iframes.]
|
||||
expected: FAIL
|
||||
|
||||
[Feature policy "microphone" can be enabled in cross-origin iframes using "allow" attribute.]
|
||||
expected: FAIL
|
||||
|
||||
[Feature policy "camera" can be enabled in cross-origin iframes using "allow" attribute.]
|
||||
expected: FAIL
|
||||
|
@ -1,7 +1,8 @@
|
||||
[permissions-policy-audio+video.https.sub.html]
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1722250
|
||||
[Default "display-capture" permissions policy ["self"\] disallows cross-origin iframes.]
|
||||
expected: FAIL
|
||||
expected:
|
||||
if os == "android": FAIL
|
||||
|
||||
[Default "display-capture" permissions policy ["self"\] allows the top-level document.]
|
||||
expected:
|
||||
@ -16,4 +17,5 @@
|
||||
if os == "android": FAIL
|
||||
|
||||
[permissions policy "display-capture" can be disabled in same-origin iframes using "allow" attribute.]
|
||||
expected: FAIL
|
||||
expected:
|
||||
if os == "android": FAIL
|
||||
|
@ -1,7 +1,8 @@
|
||||
[permissions-policy-audio.https.sub.html]
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1722250
|
||||
[Default "display-capture" permissions policy ["self"\] disallows cross-origin iframes.]
|
||||
expected: FAIL
|
||||
expected:
|
||||
if os == "android": FAIL
|
||||
|
||||
[Default "display-capture" permissions policy ["self"\] allows the top-level document.]
|
||||
expected:
|
||||
@ -16,4 +17,5 @@
|
||||
if os == "android": FAIL
|
||||
|
||||
[permissions policy "display-capture" can be disabled in same-origin iframes using "allow" attribute.]
|
||||
expected: FAIL
|
||||
expected:
|
||||
if os == "android": FAIL
|
||||
|
@ -1,7 +1,8 @@
|
||||
[permissions-policy-video.https.sub.html]
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1722250
|
||||
[Default "display-capture" permissions policy ["self"\] disallows cross-origin iframes.]
|
||||
expected: FAIL
|
||||
expected:
|
||||
if os == "android": FAIL
|
||||
|
||||
[Default "display-capture" permissions policy ["self"\] allows the top-level document.]
|
||||
expected:
|
||||
@ -16,4 +17,5 @@
|
||||
if os == "android": FAIL
|
||||
|
||||
[permissions policy "display-capture" can be disabled in same-origin iframes using "allow" attribute.]
|
||||
expected: FAIL
|
||||
expected:
|
||||
if os == "android": FAIL
|
||||
|
Loading…
Reference in New Issue
Block a user