From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../browser_devices_get_user_media_screen.js | 949 +++++++++++++++++++++ 1 file changed, 949 insertions(+) create mode 100644 browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js (limited to 'browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js') diff --git a/browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js b/browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js new file mode 100644 index 0000000000..d09d7f2c5f --- /dev/null +++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_screen.js @@ -0,0 +1,949 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// The rejection "The fetching process for the media resource was aborted by the +// user agent at the user's request." is left unhandled in some cases. This bug +// should be fixed, but for the moment this file allows a class of rejections. +// +// NOTE: Allowing a whole class of rejections should be avoided. Normally you +// should use "expectUncaughtRejection" to flag individual failures. +const { PromiseTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PromiseTestUtils.sys.mjs" +); +PromiseTestUtils.allowMatchingRejectionsGlobally(/aborted by the user agent/); + +const permissionError = + "error: NotAllowedError: The request is not allowed " + + "by the user agent or the platform in the current context."; + +const notFoundError = "error: NotFoundError: The object can not be found here."; + +const isHeadless = Services.env.get("MOZ_HEADLESS"); + +function verifyTabSharingPopup(expectedItems) { + let event = new MouseEvent("popupshowing"); + let sharingMenu = document.getElementById("tabSharingMenuPopup"); + sharingMenu.dispatchEvent(event); + + is( + sharingMenu.children.length, + expectedItems.length, + "correct number of items on tab sharing menu" + ); + for (let i = 0; i < expectedItems.length; i++) { + is( + JSON.parse(sharingMenu.children[i].getAttribute("data-l10n-args")) + .itemList, + expectedItems[i], + "label of item " + i + " + was correct" + ); + } + + sharingMenu.dispatchEvent(new MouseEvent("popuphiding")); +} + +var gTests = [ + { + desc: "getUserMedia window/screen picking screen", + run: async function checkWindowOrScreen() { + let observerPromise = expectObserverCalled("getUserMedia:request"); + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(false, true, null, "screen"); + await promise; + await observerPromise; + + is( + PopupNotifications.getNotification("webRTC-shareDevices").anchorID, + "webRTC-shareScreen-notification-icon", + "anchored to device icon" + ); + checkDeviceSelectors(["screen"]); + let notification = PopupNotifications.panel.firstElementChild; + + let menulist = document.getElementById("webRTC-selectWindow-menulist"); + let count = menulist.itemCount; + ok( + count >= 4, + "There should be the 'Select Window or Screen' item, a separator and at least one window and one screen" + ); + + let noWindowOrScreenItem = menulist.getItemAtIndex(0); + ok( + noWindowOrScreenItem.hasAttribute("selected"), + "the 'Select Window or Screen' item is selected" + ); + is( + menulist.selectedItem, + noWindowOrScreenItem, + "'Select Window or Screen' is the selected item" + ); + is(menulist.value, "-1", "no window or screen is selected by default"); + ok( + noWindowOrScreenItem.disabled, + "'Select Window or Screen' item is disabled" + ); + ok(notification.button.disabled, "Allow button is disabled"); + ok( + notification.hasAttribute("invalidselection"), + "Notification is marked as invalid" + ); + + let separator = menulist.getItemAtIndex(1); + is( + separator.localName, + "menuseparator", + "the second item is a separator" + ); + + ok( + document.getElementById("webRTC-all-windows-shared").hidden, + "the 'all windows will be shared' warning should be hidden while there's no selection" + ); + ok( + document.getElementById("webRTC-preview").hidden, + "the preview area is hidden" + ); + + let scaryScreenIndex; + for (let i = 2; i < count; ++i) { + let item = menulist.getItemAtIndex(i); + is( + parseInt(item.getAttribute("value")), + i - 2, + "the window/screen item has the correct index" + ); + let type = item.getAttribute("devicetype"); + ok( + ["window", "screen"].includes(type), + "the devicetype attribute is set correctly" + ); + if (type == "screen") { + ok(item.scary, "the screen item is marked as scary"); + scaryScreenIndex = i; + } + } + ok( + typeof scaryScreenIndex == "number", + "there's at least one scary screen, as as all screens are" + ); + + // Select a screen, a preview with a scary warning should appear. + menulist.getItemAtIndex(scaryScreenIndex).doCommand(); + ok( + !document.getElementById("webRTC-all-windows-shared").hidden, + "the 'all windows will be shared' warning should now be visible" + ); + await TestUtils.waitForCondition( + () => !document.getElementById("webRTC-preview").hidden, + "preview unhide", + 100, + 100 + ); + ok( + !document.getElementById("webRTC-preview").hidden, + "the preview area is visible" + ); + ok( + !document.getElementById("webRTC-previewWarningBox").hidden, + "the scary warning is visible" + ); + ok(!notification.button.disabled, "Allow button is enabled"); + + // Select the 'Select Window or Screen' item again, the preview should be hidden. + menulist.getItemAtIndex(0).doCommand(); + ok( + document.getElementById("webRTC-all-windows-shared").hidden, + "the 'all windows will be shared' warning should now be hidden" + ); + ok( + document.getElementById("webRTC-preview").hidden, + "the preview area is hidden" + ); + + // Select the scary screen again so that we can have a stream. + menulist.getItemAtIndex(scaryScreenIndex).doCommand(); + + let indicator = promiseIndicatorWindow(); + let observerPromise1 = expectObserverCalled( + "getUserMedia:response:allow" + ); + let observerPromise2 = expectObserverCalled("recording-device-events"); + await promiseMessage("ok", () => { + PopupNotifications.panel.firstElementChild.button.click(); + }); + await observerPromise1; + await observerPromise2; + Assert.deepEqual( + await getMediaCaptureState(), + { screen: "Screen" }, + "expected screen to be shared" + ); + + await indicator; + await checkSharingUI({ screen: "Screen" }); + verifyTabSharingPopup(["screen"]); + + // we always show prompt for screen sharing. + promise = promisePopupNotificationShown("webRTC-shareDevices"); + observerPromise = expectObserverCalled("getUserMedia:request"); + await promiseRequestDevice(false, true, null, "screen"); + await promise; + await observerPromise; + + is( + PopupNotifications.getNotification("webRTC-shareDevices").anchorID, + "webRTC-shareScreen-notification-icon", + "anchored to device icon" + ); + checkDeviceSelectors(["screen"]); + + observerPromise = expectObserverCalled("getUserMedia:response:deny"); + await promiseMessage(permissionError, () => { + activateSecondaryAction(kActionDeny); + }); + + await observerPromise; + SitePermissions.removeFromPrincipal( + null, + "screen", + gBrowser.selectedBrowser + ); + await closeStream(); + }, + }, + + { + desc: "getUserMedia window/screen picking window", + run: async function checkWindowOrScreen() { + let observerPromise = expectObserverCalled("getUserMedia:request"); + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(false, true, null, "window"); + await promise; + await observerPromise; + + is( + PopupNotifications.getNotification("webRTC-shareDevices").anchorID, + "webRTC-shareScreen-notification-icon", + "anchored to device icon" + ); + checkDeviceSelectors(["screen"]); + let notification = PopupNotifications.panel.firstElementChild; + + let menulist = document.getElementById("webRTC-selectWindow-menulist"); + let count = menulist.itemCount; + ok( + count >= 4, + "There should be the 'Select Window or Screen' item, a separator and at least one window and one screen" + ); + + let noWindowOrScreenItem = menulist.getItemAtIndex(0); + ok( + noWindowOrScreenItem.hasAttribute("selected"), + "the 'Select Window or Screen' item is selected" + ); + is( + menulist.selectedItem, + noWindowOrScreenItem, + "'Select Window or Screen' is the selected item" + ); + is(menulist.value, "-1", "no window or screen is selected by default"); + ok( + noWindowOrScreenItem.disabled, + "'Select Window or Screen' item is disabled" + ); + ok(notification.button.disabled, "Allow button is disabled"); + ok( + notification.hasAttribute("invalidselection"), + "Notification is marked as invalid" + ); + + let separator = menulist.getItemAtIndex(1); + is( + separator.localName, + "menuseparator", + "the second item is a separator" + ); + + ok( + document.getElementById("webRTC-all-windows-shared").hidden, + "the 'all windows will be shared' warning should be hidden while there's no selection" + ); + ok( + document.getElementById("webRTC-preview").hidden, + "the preview area is hidden" + ); + + let scaryWindowIndexes = [], + nonScaryWindowIndex, + scaryScreenIndex; + for (let i = 2; i < count; ++i) { + let item = menulist.getItemAtIndex(i); + is( + parseInt(item.getAttribute("value")), + i - 2, + "the window/screen item has the correct index" + ); + let type = item.getAttribute("devicetype"); + ok( + ["window", "screen"].includes(type), + "the devicetype attribute is set correctly" + ); + if (type == "screen") { + ok(item.scary, "the screen item is marked as scary"); + scaryScreenIndex = i; + } else if (item.scary) { + scaryWindowIndexes.push(i); + } else { + nonScaryWindowIndex = i; + } + } + if (isHeadless) { + is( + scaryWindowIndexes.length, + 0, + "there are no scary Firefox windows in headless mode" + ); + } else { + ok( + scaryWindowIndexes.length, + "there's at least one scary window, as Firefox is running" + ); + } + ok( + typeof scaryScreenIndex == "number", + "there's at least one scary screen, as all screens are" + ); + + if (!isHeadless) { + // Select one scary window, a preview with a scary warning should appear. + let scaryWindowIndex; + for (scaryWindowIndex of scaryWindowIndexes) { + menulist.getItemAtIndex(scaryWindowIndex).doCommand(); + ok( + document.getElementById("webRTC-all-windows-shared").hidden, + "the 'all windows will be shared' warning should still be hidden" + ); + try { + await TestUtils.waitForCondition( + () => !document.getElementById("webRTC-preview").hidden, + "", + 100, + 100 + ); + break; + } catch (e) { + // A "scary window" is Firefox. Multiple Firefox windows have been + // observed to come and go during try runs, so we won't know which one + // is ours. To avoid intermittents, we ignore preview failing due to + // these going away on us, provided it succeeds on one of them. + } + } + ok( + !document.getElementById("webRTC-preview").hidden, + "the preview area is visible" + ); + ok( + !document.getElementById("webRTC-previewWarningBox").hidden, + "the scary warning is visible" + ); + // Select the 'Select Window' item again, the preview should be hidden. + menulist.getItemAtIndex(0).doCommand(); + ok( + document.getElementById("webRTC-preview").hidden, + "the preview area is hidden" + ); + + // Select the first window again so that we can have a stream. + menulist.getItemAtIndex(scaryWindowIndex).doCommand(); + } + + let sharingNonScaryWindow = typeof nonScaryWindowIndex == "number"; + + // If we have a non-scary window, select it and verify the warning isn't displayed. + // A non-scary window may not always exist on test machines. + if (sharingNonScaryWindow) { + menulist.getItemAtIndex(nonScaryWindowIndex).doCommand(); + ok( + document.getElementById("webRTC-all-windows-shared").hidden, + "the 'all windows will be shared' warning should still be hidden" + ); + await TestUtils.waitForCondition( + () => !document.getElementById("webRTC-preview").hidden, + "preview unhide", + 100, + 100 + ); + ok( + !document.getElementById("webRTC-preview").hidden, + "the preview area is visible" + ); + ok( + document.getElementById("webRTC-previewWarningBox").hidden, + "the scary warning is hidden" + ); + } else { + info("no non-scary window available on this test machine"); + } + + let indicator = promiseIndicatorWindow(); + let observerPromise1 = expectObserverCalled( + "getUserMedia:response:allow" + ); + let observerPromise2 = expectObserverCalled("recording-device-events"); + await promiseMessage("ok", () => { + PopupNotifications.panel.firstElementChild.button.click(); + }); + await observerPromise1; + await observerPromise2; + Assert.deepEqual( + await getMediaCaptureState(), + { screen: "Window" }, + "expected screen to be shared" + ); + + await indicator; + if (sharingNonScaryWindow) { + await checkSharingUI({ screen: "Window" }); + } else { + await checkSharingUI({ screen: "Window", browserwindow: true }); + } + + verifyTabSharingPopup(["window"]); + + await closeStream(); + }, + }, + + { + desc: "getUserMedia audio + window/screen", + run: async function checkAudioVideo() { + if (AppConstants.platform == "macosx") { + todo( + false, + "Bug 1323481 - On Mac on treeherder, but not locally, requesting microphone + screen never makes the permission prompt appear, and so causes the test to timeout" + ); + return; + } + + let observerPromise = expectObserverCalled("getUserMedia:request"); + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(true, true, null, "window"); + await promise; + await observerPromise; + + is( + PopupNotifications.getNotification("webRTC-shareDevices").anchorID, + "webRTC-shareScreen-notification-icon", + "anchored to device icon" + ); + checkDeviceSelectors(["microphone", "screen"]); + + let menulist = document.getElementById("webRTC-selectWindow-menulist"); + let count = menulist.itemCount; + ok( + count >= 4, + "There should be the 'Select Window or Screen' item, a separator and at least one window and one screen" + ); + + // Select a screen, a preview with a scary warning should appear. + menulist.getItemAtIndex(count - 1).doCommand(); + ok( + !document.getElementById("webRTC-all-windows-shared").hidden, + "the 'all windows will be shared' warning should now be visible" + ); + await TestUtils.waitForCondition( + () => !document.getElementById("webRTC-preview").hidden, + "preview unhide", + 100, + 100 + ); + ok( + !document.getElementById("webRTC-preview").hidden, + "the preview area is visible" + ); + ok( + !document.getElementById("webRTC-previewWarningBox").hidden, + "the scary warning is visible" + ); + + let indicator = promiseIndicatorWindow(); + let observerPromise1 = expectObserverCalled( + "getUserMedia:response:allow" + ); + let observerPromise2 = expectObserverCalled("recording-device-events"); + await promiseMessage("ok", () => { + PopupNotifications.panel.firstElementChild.button.click(); + }); + await observerPromise1; + await observerPromise2; + Assert.deepEqual( + await getMediaCaptureState(), + { audio: true, screen: "Screen" }, + "expected screen and microphone to be shared" + ); + + await indicator; + await checkSharingUI({ audio: true, screen: "Screen" }); + + verifyTabSharingPopup(["microphone and screen"]); + + await closeStream(); + }, + }, + + { + desc: 'getUserMedia screen, user clicks "Don\'t Allow"', + run: async function checkDontShare() { + let observerPromise = expectObserverCalled("getUserMedia:request"); + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(false, true, null, "screen"); + await promise; + await observerPromise; + checkDeviceSelectors(["screen"]); + + let observerPromise1 = expectObserverCalled("getUserMedia:response:deny"); + let observerPromise2 = expectObserverCalled("recording-window-ended"); + await promiseMessage(permissionError, () => { + activateSecondaryAction(kActionDeny); + }); + + await observerPromise1; + await observerPromise2; + await checkNotSharing(); + SitePermissions.removeFromPrincipal( + null, + "screen", + gBrowser.selectedBrowser + ); + SitePermissions.removeFromPrincipal( + null, + "camera", + gBrowser.selectedBrowser + ); + }, + }, + + { + desc: "getUserMedia audio + window/screen: stop sharing", + run: async function checkStopSharing() { + if (AppConstants.platform == "macosx") { + todo( + false, + "Bug 1323481 - On Mac on treeherder, but not locally, requesting microphone + screen never makes the permission prompt appear, and so causes the test to timeout" + ); + return; + } + + async function share(deviceTypes) { + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + let observerPromise = expectObserverCalled("getUserMedia:request"); + await promiseRequestDevice( + /* audio */ deviceTypes.includes("microphone"), + /* video */ deviceTypes.some(t => t == "screen" || t == "camera"), + null, + deviceTypes.includes("screen") && "window" + ); + await promise; + await observerPromise; + checkDeviceSelectors(deviceTypes); + if (screen) { + let menulist = document.getElementById( + "webRTC-selectWindow-menulist" + ); + menulist.getItemAtIndex(menulist.itemCount - 1).doCommand(); + } + let observerPromise1 = expectObserverCalled( + "getUserMedia:response:allow" + ); + let observerPromise2 = expectObserverCalled("recording-device-events"); + await promiseMessage("ok", () => { + PopupNotifications.panel.firstElementChild.button.click(); + }); + await observerPromise1; + await observerPromise2; + } + + async function check(expected = {}, expectedSharingLabel) { + let shared = Object.keys(expected).join(" and "); + if (shared) { + Assert.deepEqual( + await getMediaCaptureState(), + expected, + "expected " + shared + " to be shared" + ); + await checkSharingUI(expected); + verifyTabSharingPopup([expectedSharingLabel]); + } else { + await checkNotSharing(); + verifyTabSharingPopup([""]); + } + } + + info("Share screen and microphone"); + let indicator = promiseIndicatorWindow(); + await share(["microphone", "screen"]); + await indicator; + await check({ audio: true, screen: "Screen" }, "microphone and screen"); + + info("Share camera"); + await share(["camera"]); + await check( + { video: true, audio: true, screen: "Screen" }, + "microphone, screen, and camera" + ); + + info("Stop the screen share, mic+cam should continue"); + await stopSharing("screen", true); + await check({ video: true, audio: true }, "microphone and camera"); + + info("Stop the camera, everything should stop."); + await stopSharing("camera"); + + info("Now, share only the screen..."); + indicator = promiseIndicatorWindow(); + await share(["screen"]); + await indicator; + await check({ screen: "Screen" }, "screen"); + + info("... and add camera and microphone in a second request."); + await share(["microphone", "camera"]); + await check( + { video: true, audio: true, screen: "Screen" }, + "screen, microphone, and camera" + ); + + info("Stop the camera, this should stop everything."); + await stopSharing("camera"); + }, + }, + + { + desc: "getUserMedia window/screen: reloading the page removes all gUM UI", + run: async function checkReloading() { + let observerPromise = expectObserverCalled("getUserMedia:request"); + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(false, true, null, "screen"); + await promise; + await observerPromise; + checkDeviceSelectors(["screen"]); + let menulist = document.getElementById("webRTC-selectWindow-menulist"); + menulist.getItemAtIndex(menulist.itemCount - 1).doCommand(); + + let indicator = promiseIndicatorWindow(); + let observerPromise1 = expectObserverCalled( + "getUserMedia:response:allow" + ); + let observerPromise2 = expectObserverCalled("recording-device-events"); + await promiseMessage("ok", () => { + PopupNotifications.panel.firstElementChild.button.click(); + }); + await observerPromise1; + await observerPromise2; + Assert.deepEqual( + await getMediaCaptureState(), + { screen: "Screen" }, + "expected screen to be shared" + ); + + await indicator; + await checkSharingUI({ screen: "Screen" }); + verifyTabSharingPopup(["screen"]); + + await reloadAndAssertClosedStreams(); + }, + }, + + { + desc: "test showControlCenter from screen icon", + run: async function checkShowControlCenter() { + if (!USING_LEGACY_INDICATOR) { + info( + "Skipping since this test doesn't apply to the new global sharing " + + "indicator." + ); + return; + } + let observerPromise = expectObserverCalled("getUserMedia:request"); + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(false, true, null, "screen"); + await promise; + await observerPromise; + checkDeviceSelectors(["screen"]); + let menulist = document.getElementById("webRTC-selectWindow-menulist"); + menulist.getItemAtIndex(menulist.itemCount - 1).doCommand(); + + let observerPromise1 = expectObserverCalled( + "getUserMedia:response:allow" + ); + let observerPromise2 = expectObserverCalled("recording-device-events"); + let indicator = promiseIndicatorWindow(); + await promiseMessage("ok", () => { + PopupNotifications.panel.firstElementChild.button.click(); + }); + await observerPromise1; + await observerPromise2; + Assert.deepEqual( + await getMediaCaptureState(), + { screen: "Screen" }, + "expected screen to be shared" + ); + await indicator; + await checkSharingUI({ screen: "Screen" }); + verifyTabSharingPopup(["screen"]); + + ok(permissionPopupHidden(), "control center should be hidden"); + if (IS_MAC) { + let activeStreams = webrtcUI.getActiveStreams(false, false, true); + webrtcUI.showSharingDoorhanger(activeStreams[0]); + } else { + let win = Services.wm.getMostRecentWindow( + "Browser:WebRTCGlobalIndicator" + ); + let elt = win.document.getElementById("screenShareButton"); + EventUtils.synthesizeMouseAtCenter(elt, {}, win); + } + await TestUtils.waitForCondition( + () => !permissionPopupHidden(), + "wait for control center to open" + ); + ok(!permissionPopupHidden(), "control center should be open"); + + gPermissionPanel._permissionPopup.hidePopup(); + + await closeStream(); + }, + }, + + { + desc: "Only persistent block is possible for screen sharing", + run: async function checkPersistentPermissions() { + // This test doesn't apply when the notification silencing + // feature is enabled, since the "Remember this decision" + // checkbox doesn't exist. + if (ALLOW_SILENCING_NOTIFICATIONS) { + return; + } + + let browser = gBrowser.selectedBrowser; + let devicePerms = SitePermissions.getForPrincipal( + browser.contentPrincipal, + "screen", + browser + ); + is( + devicePerms.state, + SitePermissions.UNKNOWN, + "starting without screen persistent permissions" + ); + + let observerPromise = expectObserverCalled("getUserMedia:request"); + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(false, true, null, "screen"); + await promise; + await observerPromise; + checkDeviceSelectors(["screen"]); + document + .getElementById("webRTC-selectWindow-menulist") + .getItemAtIndex(2) + .doCommand(); + + // Ensure that checking the 'Remember this decision' checkbox disables + // 'Allow'. + let notification = PopupNotifications.panel.firstElementChild; + ok( + notification.hasAttribute("warninghidden"), + "warning message is hidden" + ); + let checkbox = notification.checkbox; + ok(!!checkbox, "checkbox is present"); + ok(!checkbox.checked, "checkbox is not checked"); + checkbox.click(); + ok(checkbox.checked, "checkbox now checked"); + ok(notification.button.disabled, "Allow button is disabled"); + ok( + !notification.hasAttribute("warninghidden"), + "warning message is shown" + ); + + // Click "Don't Allow" to save a persistent block permission. + let observerPromise1 = expectObserverCalled("getUserMedia:response:deny"); + let observerPromise2 = expectObserverCalled("recording-window-ended"); + await promiseMessage(permissionError, () => { + activateSecondaryAction(kActionDeny); + }); + await observerPromise1; + await observerPromise2; + await checkNotSharing(); + + let permission = SitePermissions.getForPrincipal( + browser.contentPrincipal, + "screen", + browser + ); + is(permission.state, SitePermissions.BLOCK, "screen sharing is blocked"); + is( + permission.scope, + SitePermissions.SCOPE_PERSISTENT, + "screen sharing is persistently blocked" + ); + + // Request screensharing again, expect an immediate failure. + 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( + browser.contentPrincipal, + "screen", + SitePermissions.ALLOW + ); + + // Request devices and expect a prompt despite the saved 'Allow' permission. + observerPromise = expectObserverCalled("getUserMedia:request"); + promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(false, true, null, "screen"); + await promise; + await observerPromise; + + // The 'remember' checkbox shouldn't be checked anymore. + notification = PopupNotifications.panel.firstElementChild; + ok( + notification.hasAttribute("warninghidden"), + "warning message is hidden" + ); + checkbox = notification.checkbox; + ok(!!checkbox, "checkbox is present"); + ok(!checkbox.checked, "checkbox is not checked"); + + // Deny the request to cleanup... + observerPromise1 = expectObserverCalled("getUserMedia:response:deny"); + observerPromise2 = expectObserverCalled("recording-window-ended"); + await promiseMessage(permissionError, () => { + activateSecondaryAction(kActionDeny); + }); + await observerPromise1; + await observerPromise2; + SitePermissions.removeFromPrincipal( + browser.contentPrincipal, + "screen", + browser + ); + }, + }, + + { + desc: "Switching between menu options maintains correct main action state while window sharing", + skipObserverVerification: true, + run: async function checkDoorhangerState() { + await enableObserverVerification(); + + let win = await BrowserTestUtils.openNewBrowserWindow(); + await BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:newtab"); + BrowserWindowTracker.orderedWindows[1].focus(); + + let observerPromise = expectObserverCalled("getUserMedia:request"); + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(false, true, null, "window"); + await promise; + await observerPromise; + + let menulist = document.getElementById("webRTC-selectWindow-menulist"); + let notification = PopupNotifications.panel.firstElementChild; + let checkbox = notification.checkbox; + + menulist.getItemAtIndex(2).doCommand(); + checkbox.click(); + ok(checkbox.checked, "checkbox now checked"); + + if (ALLOW_SILENCING_NOTIFICATIONS) { + // When the notification silencing feature is enabled, the checkbox + // controls that feature, and its state should not disable the + // "Allow" button. + ok(!notification.button.disabled, "Allow button is not disabled"); + } else { + ok(notification.button.disabled, "Allow button is disabled"); + ok( + !notification.hasAttribute("warninghidden"), + "warning message is shown" + ); + } + + menulist.getItemAtIndex(3).doCommand(); + ok(checkbox.checked, "checkbox still checked"); + if (ALLOW_SILENCING_NOTIFICATIONS) { + // When the notification silencing feature is enabled, the checkbox + // controls that feature, and its state should not disable the + // "Allow" button. + ok(!notification.button.disabled, "Allow button remains not disabled"); + } else { + ok(notification.button.disabled, "Allow button remains disabled"); + ok( + !notification.hasAttribute("warninghidden"), + "warning message is still shown" + ); + } + + await disableObserverVerification(); + + observerPromise = expectObserverCalled("recording-window-ended"); + + gBrowser.removeCurrentTab(); + win.close(); + + await observerPromise; + + await openNewTestTab(); + }, + }, + { + desc: "Switching between tabs does not bleed state into other prompts", + skipObserverVerification: true, + run: async function checkSwitchingTabs() { + // Open a new window in the background to have a choice in the menulist. + let win = await BrowserTestUtils.openNewBrowserWindow(); + await BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:newtab"); + await enableObserverVerification(); + BrowserWindowTracker.orderedWindows[1].focus(); + + let observerPromise = expectObserverCalled("getUserMedia:request"); + let promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(false, true, null, "window"); + await promise; + await observerPromise; + + let notification = PopupNotifications.panel.firstElementChild; + ok(notification.button.disabled, "Allow button is disabled"); + await disableObserverVerification(); + + await openNewTestTab("get_user_media_in_xorigin_frame.html"); + await enableObserverVerification(); + + observerPromise = expectObserverCalled("getUserMedia:request"); + promise = promisePopupNotificationShown("webRTC-shareDevices"); + await promiseRequestDevice(true, true, "frame1"); + await promise; + await observerPromise; + + notification = PopupNotifications.panel.firstElementChild; + ok(!notification.button.disabled, "Allow button is not disabled"); + + await disableObserverVerification(); + + gBrowser.removeCurrentTab(); + gBrowser.removeCurrentTab(); + win.close(); + + await openNewTestTab(); + }, + }, +]; + +add_task(async function test() { + await runTests(gTests); +}); -- cgit v1.2.3