Bug 1703674 - Revoking cam or mic permission revokes both if either is capturing. r=pbz

Differential Revision: https://phabricator.services.mozilla.com/D111174
This commit is contained in:
Jan-Ivar Bruaroey 2021-04-09 20:48:41 +00:00
Родитель 492ca0fcc5
Коммит 13771db18d
3 изменённых файлов: 100 добавлений и 65 удалений

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

@ -653,7 +653,12 @@ var gTests = [
{ {
desc: "Stop Sharing removes permissions", desc: "Stop Sharing removes permissions",
run: async function checkStopSharingRemovesPermissions() { run: async function checkStopSharingRemovesPermissions() {
async function stopAndCheckPerm(aRequestAudio, aRequestVideo) { async function stopAndCheckPerm(
aRequestAudio,
aRequestVideo,
aStopAudio = aRequestAudio,
aStopVideo = aRequestVideo
) {
let uri = gBrowser.selectedBrowser.documentURI; let uri = gBrowser.selectedBrowser.documentURI;
// Initially set both permissions to 'allow'. // Initially set both permissions to 'allow'.
@ -677,32 +682,37 @@ var gTests = [
10000000 10000000
); );
let indicator = promiseIndicatorWindow(); if (aRequestAudio || aRequestVideo) {
let observerPromise1 = expectObserverCalled("getUserMedia:request"); let indicator = promiseIndicatorWindow();
let observerPromise2 = expectObserverCalled( let observerPromise1 = expectObserverCalled("getUserMedia:request");
"getUserMedia:response:allow" let observerPromise2 = expectObserverCalled(
); "getUserMedia:response:allow"
let observerPromise3 = expectObserverCalled("recording-device-events"); );
// Start sharing what's been requested. let observerPromise3 = expectObserverCalled(
let promise = promiseMessage("ok"); "recording-device-events"
await promiseRequestDevice(aRequestAudio, aRequestVideo); );
await promise; // Start sharing what's been requested.
await observerPromise1; let promise = promiseMessage("ok");
await observerPromise2; await promiseRequestDevice(aRequestAudio, aRequestVideo);
await observerPromise3; await promise;
await observerPromise1;
await observerPromise2;
await observerPromise3;
await indicator; await indicator;
await checkSharingUI( await checkSharingUI(
{ video: aRequestVideo, audio: aRequestAudio }, { video: aRequestVideo, audio: aRequestAudio },
undefined, undefined,
undefined, undefined,
{ {
video: { scope: SitePermissions.SCOPE_PERSISTENT }, video: { scope: SitePermissions.SCOPE_PERSISTENT },
audio: { scope: SitePermissions.SCOPE_PERSISTENT }, audio: { scope: SitePermissions.SCOPE_PERSISTENT },
} }
); );
await stopSharing(aStopVideo ? "camera" : "microphone");
await stopSharing(aRequestVideo ? "camera" : "microphone"); } else {
await revokePermission(aStopVideo ? "camera" : "microphone");
}
// Check that permissions have been removed as expected. // Check that permissions have been removed as expected.
let audioPerm = SitePermissions.getForPrincipal( let audioPerm = SitePermissions.getForPrincipal(
@ -716,7 +726,12 @@ var gTests = [
gBrowser.selectedBrowser gBrowser.selectedBrowser
); );
if (aRequestAudio) { if (
aRequestAudio ||
aRequestVideo ||
aStopAudio ||
(aStopVideo && aRequestAudio)
) {
Assert.deepEqual( Assert.deepEqual(
audioPerm, audioPerm,
{ {
@ -762,7 +777,12 @@ var gTests = [
"camera^myDevice2", "camera^myDevice2",
gBrowser.selectedBrowser gBrowser.selectedBrowser
); );
if (aRequestVideo) { if (
aRequestAudio ||
aRequestVideo ||
aStopVideo ||
(aStopAudio && aRequestVideo)
) {
Assert.deepEqual( Assert.deepEqual(
videoPerm, videoPerm,
{ {
@ -797,6 +817,7 @@ var gTests = [
"camera device-specific permissions untouched" "camera device-specific permissions untouched"
); );
} }
await checkNotSharing();
// Cleanup. // Cleanup.
await closeStream(true); await closeStream(true);
@ -813,12 +834,20 @@ var gTests = [
); );
} }
info("request audio+video, stop sharing resets both"); info("request audio+video, stop sharing video resets both");
await stopAndCheckPerm(true, true); await stopAndCheckPerm(true, true);
info("request audio, stop sharing resets audio only"); info("request audio only, stop sharing audio resets both");
await stopAndCheckPerm(true, false); await stopAndCheckPerm(true, false);
info("request video, stop sharing resets video only"); info("request video only, stop sharing video resets both");
await stopAndCheckPerm(false, true); await stopAndCheckPerm(false, true);
info("request audio only, stop sharing video resets both");
await stopAndCheckPerm(true, false, false, true);
info("request video only, stop sharing audio resets both");
await stopAndCheckPerm(false, true, true, false);
info("request neither, stop audio affects audio only");
await stopAndCheckPerm(false, false, true, false);
info("request neither, stop video affects video only");
await stopAndCheckPerm(false, false, false, true);
}, },
}, },

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

@ -582,22 +582,6 @@ async function stopSharing(
1, 1,
aFrameBC aFrameBC
); );
aWindow.gPermissionPanel._identityPermissionBox.click();
let popup = aWindow.gPermissionPanel._permissionPopup;
// If the popup gets hidden before being shown, by stray focus/activate
// events, don't bother failing the test. It's enough to know that we
// started showing the popup.
let hiddenEvent = BrowserTestUtils.waitForEvent(popup, "popuphidden");
let shownEvent = BrowserTestUtils.waitForEvent(popup, "popupshown");
await Promise.race([hiddenEvent, shownEvent]);
let doc = aWindow.document;
let permissions = doc.getElementById("permission-popup-permission-list");
let cancelButton = permissions.querySelector(
".permission-popup-permission-icon." +
aType +
"-icon ~ " +
".permission-popup-permission-remove-button"
);
let observerPromise1 = expectObserverCalled( let observerPromise1 = expectObserverCalled(
"getUserMedia:revoke", "getUserMedia:revoke",
1, 1,
@ -615,9 +599,7 @@ async function stopSharing(
); );
} }
cancelButton.click(); await revokePermission(aType, aShouldKeepSharing, aFrameBC, aWindow);
popup.hidePopup();
await promiseRecordingEvent; await promiseRecordingEvent;
await observerPromise1; await observerPromise1;
await observerPromise2; await observerPromise2;
@ -627,6 +609,37 @@ async function stopSharing(
} }
} }
async function revokePermission(
aType = "camera",
aShouldKeepSharing = false,
aFrameBC,
aWindow = window
) {
aWindow.gPermissionPanel._identityPermissionBox.click();
let popup = aWindow.gPermissionPanel._permissionPopup;
// If the popup gets hidden before being shown, by stray focus/activate
// events, don't bother failing the test. It's enough to know that we
// started showing the popup.
let hiddenEvent = BrowserTestUtils.waitForEvent(popup, "popuphidden");
let shownEvent = BrowserTestUtils.waitForEvent(popup, "popupshown");
await Promise.race([hiddenEvent, shownEvent]);
let doc = aWindow.document;
let permissions = doc.getElementById("permission-popup-permission-list");
let cancelButton = permissions.querySelector(
".permission-popup-permission-icon." +
aType +
"-icon ~ " +
".permission-popup-permission-remove-button"
);
cancelButton.click();
popup.hidePopup();
if (!aShouldKeepSharing) {
await checkNotSharing();
}
}
function getBrowsingContextForFrame(aBrowsingContext, aFrameId) { function getBrowsingContextForFrame(aBrowsingContext, aFrameId) {
if (!aFrameId) { if (!aFrameId) {
return aBrowsingContext; return aBrowsingContext;

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

@ -600,22 +600,18 @@ var webrtcUI = {
// devices related to the permission. // devices related to the permission.
let perms = SitePermissions.getAllForBrowser(browser); let perms = SitePermissions.getAllForBrowser(browser);
let sharingCameraAndMic = // If capturing, don't revoke one of camera/microphone without the other.
sharingState?.camera && let sharingCameraOrMic =
sharingState?.microphone && (sharingState?.camera || sharingState?.microphone) &&
(types.includes("camera") || types.includes("microphone")); (types.includes("camera") || types.includes("microphone"));
perms perms
.filter(perm => { .filter(perm => {
let [permId] = perm.id.split(SitePermissions.PERM_KEY_DELIMITER); let [id] = perm.id.split(SitePermissions.PERM_KEY_DELIMITER);
// It's not possible to stop sharing one of camera/microphone if (sharingCameraOrMic && (id == "camera" || id == "microphone")) {
// without the other.
if (
sharingCameraAndMic &&
(permId == "camera" || permId == "microphone")
) {
return true; return true;
} }
return types.includes(permId); return types.includes(id);
}) })
.forEach(perm => { .forEach(perm => {
SitePermissions.removeFromPrincipal( SitePermissions.removeFromPrincipal(
@ -637,10 +633,7 @@ var webrtcUI = {
if (types.includes("screen") && sharingState.screen) { if (types.includes("screen") && sharingState.screen) {
windowIds.push(`screen:${windowId}`); windowIds.push(`screen:${windowId}`);
} }
if ( if (sharingCameraOrMic) {
(types.includes("camera") && sharingState.camera) ||
(types.includes("microphone") && sharingState.microphone)
) {
windowIds.push(windowId); windowIds.push(windowId);
} }