summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame.js')
-rw-r--r--browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame.js798
1 files changed, 798 insertions, 0 deletions
diff --git a/browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame.js b/browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame.js
new file mode 100644
index 0000000000..8c0b0476f3
--- /dev/null
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame.js
@@ -0,0 +1,798 @@
+/* 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/. */
+const permissionError =
+ "error: NotAllowedError: The request is not allowed " +
+ "by the user agent or the platform in the current context.";
+
+const PromptResult = {
+ ALLOW: "allow",
+ DENY: "deny",
+ PROMPT: "prompt",
+};
+
+const Perms = Services.perms;
+
+async function promptNoDelegate(aThirdPartyOrgin, audio = true, video = true) {
+ // Persistent allowed first party origin
+ const uri = gBrowser.selectedBrowser.documentURI;
+ if (audio) {
+ PermissionTestUtils.add(uri, "microphone", Services.perms.ALLOW_ACTION);
+ }
+ if (video) {
+ PermissionTestUtils.add(uri, "camera", Services.perms.ALLOW_ACTION);
+ }
+
+ // Check that we get a prompt.
+ const observerPromise = expectObserverCalled("getUserMedia:request");
+ const promise = promisePopupNotificationShown("webRTC-shareDevices");
+ await promiseRequestDevice(audio, video, "frame4");
+ await promise;
+ await observerPromise;
+
+ // The 'Remember this decision' checkbox is hidden.
+ const notification = PopupNotifications.panel.firstElementChild;
+ const checkbox = notification.checkbox;
+ ok(!!checkbox, "checkbox is present");
+ ok(checkbox.hidden, "checkbox is not visible");
+ ok(!checkbox.checked, "checkbox not checked");
+
+ // Check the label of the notification should be the first party
+ is(
+ PopupNotifications.getNotification("webRTC-shareDevices").options.name,
+ uri.host,
+ "Use first party's origin"
+ );
+
+ // Check the secondName of the notification should be the third party
+ is(
+ PopupNotifications.getNotification("webRTC-shareDevices").options
+ .secondName,
+ aThirdPartyOrgin,
+ "Use third party's origin as secondName"
+ );
+
+ let indicator = promiseIndicatorWindow();
+ let observerPromise1 = expectObserverCalled("getUserMedia:response:allow");
+ let observerPromise2 = expectObserverCalled("recording-device-events");
+ await promiseMessage("ok", () =>
+ EventUtils.synthesizeMouseAtCenter(notification.button, {})
+ );
+ await observerPromise1;
+ await observerPromise2;
+ let state = await getMediaCaptureState();
+ is(
+ !!state.audio,
+ audio,
+ `expected microphone to be ${audio ? "" : "not"} shared`
+ );
+ is(
+ !!state.video,
+ video,
+ `expected camera to be ${video ? "" : "not"} shared`
+ );
+ await indicator;
+ await checkSharingUI({ audio, video }, undefined, undefined, {
+ video: { scope: SitePermissions.SCOPE_PERSISTENT },
+ audio: { scope: SitePermissions.SCOPE_PERSISTENT },
+ });
+
+ // Cleanup.
+ await closeStream(false, "frame4");
+
+ PermissionTestUtils.remove(uri, "camera");
+ PermissionTestUtils.remove(uri, "microphone");
+}
+
+async function promptNoDelegateScreenSharing(aThirdPartyOrgin) {
+ // Persistent allow screen sharing
+ const uri = gBrowser.selectedBrowser.documentURI;
+ PermissionTestUtils.add(uri, "screen", Services.perms.ALLOW_ACTION);
+
+ const observerPromise = expectObserverCalled("getUserMedia:request");
+ const promise = promisePopupNotificationShown("webRTC-shareDevices");
+ await promiseRequestDevice(false, true, "frame4", "screen");
+ await promise;
+ await observerPromise;
+
+ checkDeviceSelectors(["screen"]);
+ const notification = PopupNotifications.panel.firstElementChild;
+
+ // The 'Remember this decision' checkbox is hidden.
+ const checkbox = notification.checkbox;
+ ok(!!checkbox, "checkbox is present");
+
+ if (ALLOW_SILENCING_NOTIFICATIONS) {
+ ok(!checkbox.hidden, "Notification silencing checkbox is visible");
+ } else {
+ ok(checkbox.hidden, "checkbox is not visible");
+ }
+
+ ok(!checkbox.checked, "checkbox not checked");
+
+ // Check the label of the notification should be the first party
+ is(
+ PopupNotifications.getNotification("webRTC-shareDevices").options.name,
+ uri.host,
+ "Use first party's origin"
+ );
+
+ // Check the secondName of the notification should be the third party
+ is(
+ PopupNotifications.getNotification("webRTC-shareDevices").options
+ .secondName,
+ aThirdPartyOrgin,
+ "Use third party's origin as secondName"
+ );
+
+ const menulist = document.getElementById("webRTC-selectWindow-menulist");
+ const count = menulist.itemCount;
+ menulist.getItemAtIndex(count - 1).doCommand();
+ ok(!notification.button.disabled, "Allow button is enabled");
+
+ const indicator = promiseIndicatorWindow();
+ const observerPromise1 = expectObserverCalled("getUserMedia:response:allow");
+ const observerPromise2 = expectObserverCalled("recording-device-events");
+ await promiseMessage("ok", () =>
+ EventUtils.synthesizeMouseAtCenter(notification.button, {})
+ );
+ await observerPromise1;
+ await observerPromise2;
+ Assert.deepEqual(
+ await getMediaCaptureState(),
+ { screen: "Screen" },
+ "expected screen to be shared"
+ );
+
+ await indicator;
+ await checkSharingUI({ screen: "Screen" }, undefined, undefined, {
+ screen: { scope: SitePermissions.SCOPE_PERSISTENT },
+ });
+ await closeStream(false, "frame4");
+
+ PermissionTestUtils.remove(uri, "screen");
+}
+
+var gTests = [
+ {
+ desc: "'Always Allow' enabled on third party pages, when origin is explicitly allowed",
+ run: async function checkNoAlwaysOnThirdParty() {
+ // Initially set both permissions to 'prompt'.
+ const uri = gBrowser.selectedBrowser.documentURI;
+ PermissionTestUtils.add(uri, "microphone", Services.perms.PROMPT_ACTION);
+ PermissionTestUtils.add(uri, "camera", Services.perms.PROMPT_ACTION);
+
+ const observerPromise = expectObserverCalled("getUserMedia:request");
+ const promise = promisePopupNotificationShown("webRTC-shareDevices");
+ await promiseRequestDevice(true, true, "frame1");
+ await promise;
+ await observerPromise;
+ checkDeviceSelectors(["microphone", "camera"]);
+
+ // The 'Remember this decision' checkbox is visible.
+ const notification = PopupNotifications.panel.firstElementChild;
+ const checkbox = notification.checkbox;
+ ok(!!checkbox, "checkbox is present");
+ ok(!checkbox.hidden, "checkbox is visible");
+ ok(!checkbox.checked, "checkbox not checked");
+
+ // Check the label of the notification should be the first party
+ is(
+ PopupNotifications.getNotification("webRTC-shareDevices").options.name,
+ uri.host,
+ "Use first party's origin"
+ );
+
+ const indicator = promiseIndicatorWindow();
+ const observerPromise1 = expectObserverCalled(
+ "getUserMedia:response:allow"
+ );
+ const observerPromise2 = expectObserverCalled("recording-device-events");
+ await promiseMessage("ok", () =>
+ EventUtils.synthesizeMouseAtCenter(notification.button, {})
+ );
+ await observerPromise1;
+ await observerPromise2;
+ Assert.deepEqual(
+ await getMediaCaptureState(),
+ { audio: true, video: true },
+ "expected camera and microphone to be shared"
+ );
+ await indicator;
+ await checkSharingUI({ audio: true, video: true });
+
+ // Cleanup.
+ await closeStream(false, "frame1");
+ PermissionTestUtils.remove(uri, "camera");
+ PermissionTestUtils.remove(uri, "microphone");
+ },
+ },
+ {
+ desc: "'Always Allow' disabled when sharing screen in third party iframes, when origin is explicitly allowed",
+ run: async function checkScreenSharing() {
+ const observerPromise = expectObserverCalled("getUserMedia:request");
+ const promise = promisePopupNotificationShown("webRTC-shareDevices");
+ await promiseRequestDevice(false, true, "frame1", "screen");
+ await promise;
+ await observerPromise;
+
+ checkDeviceSelectors(["screen"]);
+ const notification = PopupNotifications.panel.firstElementChild;
+
+ // The 'Remember this decision' checkbox is visible.
+ const checkbox = notification.checkbox;
+ ok(!!checkbox, "checkbox is present");
+ ok(!checkbox.hidden, "checkbox is visible");
+ ok(!checkbox.checked, "checkbox not checked");
+
+ const menulist = document.getElementById("webRTC-selectWindow-menulist");
+ const 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"
+ );
+
+ const 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"
+ );
+
+ menulist.getItemAtIndex(count - 1).doCommand();
+ ok(!notification.button.disabled, "Allow button is enabled");
+
+ const indicator = promiseIndicatorWindow();
+ const observerPromise1 = expectObserverCalled(
+ "getUserMedia:response:allow"
+ );
+ const observerPromise2 = expectObserverCalled("recording-device-events");
+ await promiseMessage("ok", () =>
+ EventUtils.synthesizeMouseAtCenter(notification.button, {})
+ );
+ await observerPromise1;
+ await observerPromise2;
+ Assert.deepEqual(
+ await getMediaCaptureState(),
+ { screen: "Screen" },
+ "expected screen to be shared"
+ );
+
+ await indicator;
+ await checkSharingUI({ screen: "Screen" });
+ await closeStream(false, "frame1");
+ },
+ },
+
+ {
+ desc: "getUserMedia use persistent permissions from first party",
+ run: async function checkUsePersistentPermissionsFirstParty() {
+ async function checkPersistentPermission(
+ aPermission,
+ aRequestType,
+ aIframeId,
+ aExpect
+ ) {
+ info(
+ `Test persistent permission ${aPermission} type ${aRequestType} expect ${aExpect}`
+ );
+ const uri = gBrowser.selectedBrowser.documentURI;
+ // Persistent allow/deny for first party uri
+ PermissionTestUtils.add(uri, aRequestType, aPermission);
+
+ let audio = aRequestType == "microphone";
+ let video = aRequestType == "camera";
+ const screen = aRequestType == "screen" ? "screen" : undefined;
+ if (screen) {
+ audio = false;
+ video = true;
+ }
+ if (aExpect == PromptResult.PROMPT) {
+ // Check that we get a prompt.
+ const observerPromise = expectObserverCalled("getUserMedia:request");
+ const observerPromise1 = expectObserverCalled(
+ "getUserMedia:response:deny"
+ );
+ const observerPromise2 = expectObserverCalled(
+ "recording-window-ended"
+ );
+ const promise = promisePopupNotificationShown("webRTC-shareDevices");
+ await promiseRequestDevice(audio, video, aIframeId, screen);
+ await promise;
+ await observerPromise;
+
+ // Check the label of the notification should be the first party
+ is(
+ PopupNotifications.getNotification("webRTC-shareDevices").options
+ .name,
+ uri.host,
+ "Use first party's origin"
+ );
+
+ // Deny the request to cleanup...
+ await promiseMessage(permissionError, () => {
+ activateSecondaryAction(kActionDeny);
+ });
+ await observerPromise1;
+ await observerPromise2;
+ let browser = gBrowser.selectedBrowser;
+ SitePermissions.removeFromPrincipal(null, aRequestType, browser);
+ } else if (aExpect == PromptResult.ALLOW) {
+ const observerPromise = expectObserverCalled("getUserMedia:request");
+ const observerPromise1 = expectObserverCalled(
+ "getUserMedia:response:allow"
+ );
+ const observerPromise2 = expectObserverCalled(
+ "recording-device-events"
+ );
+ const promise = promiseMessage("ok");
+ await promiseRequestDevice(audio, video, aIframeId, screen);
+ await promise;
+ await observerPromise;
+
+ await promiseNoPopupNotification("webRTC-shareDevices");
+ await observerPromise1;
+ await observerPromise2;
+
+ let expected = {};
+ if (audio) {
+ expected.audio = audio;
+ }
+ if (video) {
+ expected.video = video;
+ }
+
+ Assert.deepEqual(
+ await getMediaCaptureState(),
+ expected,
+ "expected " + Object.keys(expected).join(" and ") + " to be shared"
+ );
+
+ await closeStream(false, aIframeId);
+ } else if (aExpect == PromptResult.DENY) {
+ 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)
+ );
+ await Promise.all(promises);
+ }
+
+ PermissionTestUtils.remove(uri, aRequestType);
+ }
+
+ await checkPersistentPermission(
+ Perms.PROMPT_ACTION,
+ "camera",
+ "frame1",
+ PromptResult.PROMPT
+ );
+ await checkPersistentPermission(
+ Perms.DENY_ACTION,
+ "camera",
+ "frame1",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.ALLOW_ACTION,
+ "camera",
+ "frame1",
+ PromptResult.ALLOW
+ );
+
+ await checkPersistentPermission(
+ Perms.PROMPT_ACTION,
+ "microphone",
+ "frame1",
+ PromptResult.PROMPT
+ );
+ await checkPersistentPermission(
+ Perms.DENY_ACTION,
+ "microphone",
+ "frame1",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.ALLOW_ACTION,
+ "microphone",
+ "frame1",
+ PromptResult.ALLOW
+ );
+
+ // Wildcard attributes still get delegation when their src is unchanged.
+ await checkPersistentPermission(
+ Perms.PROMPT_ACTION,
+ "camera",
+ "frame4",
+ PromptResult.PROMPT
+ );
+ await checkPersistentPermission(
+ Perms.DENY_ACTION,
+ "camera",
+ "frame4",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.ALLOW_ACTION,
+ "camera",
+ "frame4",
+ PromptResult.ALLOW
+ );
+
+ // Wildcard attributes still get delegation when their src is unchanged.
+ await checkPersistentPermission(
+ Perms.PROMPT_ACTION,
+ "microphone",
+ "frame4",
+ PromptResult.PROMPT
+ );
+ await checkPersistentPermission(
+ Perms.DENY_ACTION,
+ "microphone",
+ "frame4",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.ALLOW_ACTION,
+ "microphone",
+ "frame4",
+ PromptResult.ALLOW
+ );
+
+ await checkPersistentPermission(
+ Perms.PROMPT_ACTION,
+ "screen",
+ "frame1",
+ PromptResult.PROMPT
+ );
+ await checkPersistentPermission(
+ Perms.DENY_ACTION,
+ "screen",
+ "frame1",
+ PromptResult.DENY
+ );
+ // Always prompt screen sharing
+ await checkPersistentPermission(
+ Perms.ALLOW_ACTION,
+ "screen",
+ "frame1",
+ PromptResult.PROMPT
+ );
+ await checkPersistentPermission(
+ Perms.ALLOW_ACTION,
+ "screen",
+ "frame4",
+ PromptResult.PROMPT
+ );
+
+ // Denied by default if allow is not defined
+ await checkPersistentPermission(
+ Perms.PROMPT_ACTION,
+ "camera",
+ "frame3",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.DENY_ACTION,
+ "camera",
+ "frame3",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.ALLOW_ACTION,
+ "camera",
+ "frame3",
+ PromptResult.DENY
+ );
+
+ await checkPersistentPermission(
+ Perms.PROMPT_ACTION,
+ "microphone",
+ "frame3",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.DENY_ACTION,
+ "microphone",
+ "frame3",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.ALLOW_ACTION,
+ "microphone",
+ "frame3",
+ PromptResult.DENY
+ );
+
+ await checkPersistentPermission(
+ Perms.PROMPT_ACTION,
+ "screen",
+ "frame3",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.DENY_ACTION,
+ "screen",
+ "frame3",
+ PromptResult.DENY
+ );
+ await checkPersistentPermission(
+ Perms.ALLOW_ACTION,
+ "screen",
+ "frame3",
+ PromptResult.DENY
+ );
+ },
+ },
+
+ {
+ desc: "getUserMedia use temporary blocked permissions from first party",
+ run: async function checkUseTempPermissionsBlockFirstParty() {
+ async function checkTempPermission(aRequestType) {
+ let browser = gBrowser.selectedBrowser;
+ let observerPromise = expectObserverCalled("getUserMedia:request");
+ let observerPromise1 = expectObserverCalled(
+ "getUserMedia:response:deny"
+ );
+ let observerPromise2 = expectObserverCalled("recording-window-ended");
+ let promise = promisePopupNotificationShown("webRTC-shareDevices");
+ let audio = aRequestType == "microphone";
+ let video = aRequestType == "camera";
+ const screen = aRequestType == "screen" ? "screen" : undefined;
+ if (screen) {
+ audio = false;
+ video = true;
+ }
+
+ await promiseRequestDevice(audio, video, null, screen);
+ await promise;
+ await observerPromise;
+
+ // Temporarily grant/deny from top level
+ // Only need to check allow and deny temporary permissions
+ await promiseMessage(permissionError, () => {
+ activateSecondaryAction(kActionDeny);
+ });
+ await observerPromise1;
+ await observerPromise2;
+ await checkNotSharing();
+
+ observerPromise = expectObserverCalled("getUserMedia:request");
+ observerPromise1 = expectObserverCalled("getUserMedia:response:deny");
+ observerPromise2 = expectObserverCalled("recording-window-ended");
+ promise = promiseMessage(permissionError);
+ await promiseRequestDevice(audio, video, "frame1", screen);
+ await promise;
+
+ await observerPromise;
+ await observerPromise1;
+ await observerPromise2;
+
+ SitePermissions.removeFromPrincipal(null, aRequestType, browser);
+ }
+
+ // At the moment we only save temporary deny
+ await checkTempPermission("camera");
+ await checkTempPermission("microphone");
+ await checkTempPermission("screen");
+ },
+ },
+ {
+ desc: "Don't reprompt while actively sharing in maybe unsafe permission delegation",
+ run: async function checkNoRepromptNoDelegate() {
+ // Change location to ensure that we're treated as potentially unsafe.
+ await promiseChangeLocationFrame(
+ "frame4",
+ "https://test2.example.com/browser/browser/base/content/test/webrtc/get_user_media.html"
+ );
+
+ // Check that we get a prompt.
+ let observerPromise = expectObserverCalled("getUserMedia:request");
+ let promise = promisePopupNotificationShown("webRTC-shareDevices");
+ await promiseRequestDevice(true, true, "frame4");
+ await promise;
+ await observerPromise;
+
+ // Check the secondName of the notification should be the third party
+ is(
+ PopupNotifications.getNotification("webRTC-shareDevices").options
+ .secondName,
+ "test2.example.com",
+ "Use third party's origin as secondName"
+ );
+
+ const notification = PopupNotifications.panel.firstElementChild;
+ let indicator = promiseIndicatorWindow();
+ let observerPromise1 = expectObserverCalled(
+ "getUserMedia:response:allow"
+ );
+ let observerPromise2 = expectObserverCalled("recording-device-events");
+ await promiseMessage("ok", () =>
+ EventUtils.synthesizeMouseAtCenter(notification.button, {})
+ );
+ await observerPromise1;
+ await observerPromise2;
+
+ let state = await getMediaCaptureState();
+ is(!!state.audio, true, "expected microphone to be shared");
+ is(!!state.video, true, "expected camera to be shared");
+ await indicator;
+ await checkSharingUI({ audio: true, video: true });
+
+ // Check that we now don't get a prompt.
+ observerPromise = expectObserverCalled("getUserMedia:request");
+ observerPromise1 = expectObserverCalled("getUserMedia:response:allow");
+ observerPromise2 = expectObserverCalled("recording-device-events");
+ promise = promiseMessage("ok");
+ await promiseRequestDevice(true, true, "frame4");
+ await promise;
+ await observerPromise;
+
+ await promiseNoPopupNotification("webRTC-shareDevices");
+ await observerPromise1;
+ await observerPromise2;
+
+ state = await getMediaCaptureState();
+ is(!!state.audio, true, "expected microphone to be shared");
+ is(!!state.video, true, "expected camera to be shared");
+ await checkSharingUI({ audio: true, video: true });
+
+ // Cleanup.
+ await closeStream(false, "frame4");
+ },
+ },
+ {
+ desc: "Change location, prompt and display both first party and third party origin in maybe unsafe permission delegation",
+ run: async function checkPromptNoDelegateChangeLoxation() {
+ await promiseChangeLocationFrame(
+ "frame4",
+ "https://test2.example.com/browser/browser/base/content/test/webrtc/get_user_media.html"
+ );
+ await promptNoDelegate("test2.example.com");
+ },
+ },
+ {
+ desc: "Change location, prompt and display both first party and third party origin when sharing screen in unsafe permission delegation",
+ run: async function checkPromptNoDelegateScreenSharingChangeLocation() {
+ await promiseChangeLocationFrame(
+ "frame4",
+ "https://test2.example.com/browser/browser/base/content/test/webrtc/get_user_media.html"
+ );
+ await promptNoDelegateScreenSharing("test2.example.com");
+ },
+ },
+ {
+ desc: "Prompt and display both first party and third party origin and temporary deny in frame does not change permission scope",
+ skipObserverVerification: true,
+ run: async function checkPromptBothOriginsTempDenyFrame() {
+ // Change location to ensure that we're treated as potentially unsafe.
+ await promiseChangeLocationFrame(
+ "frame4",
+ "https://test2.example.com/browser/browser/base/content/test/webrtc/get_user_media.html"
+ );
+
+ // Persistent allowed first party origin
+ let browser = gBrowser.selectedBrowser;
+ let uri = gBrowser.selectedBrowser.documentURI;
+ let principal = Services.scriptSecurityManager.createContentPrincipal(
+ uri,
+ {}
+ );
+
+ let observerPromise = expectObserverCalled("getUserMedia:request");
+ let promise = promisePopupNotificationShown("webRTC-shareDevices");
+ await promiseRequestDevice(true, true);
+ await promise;
+ await observerPromise;
+
+ // Ensure that checking the 'Remember this decision'
+ let notification = PopupNotifications.panel.firstElementChild;
+ let checkbox = notification.checkbox;
+ ok(!!checkbox, "checkbox is present");
+ ok(!checkbox.checked, "checkbox is not checked");
+ checkbox.click();
+
+ let indicator = promiseIndicatorWindow();
+ let observerPromise1 = expectObserverCalled(
+ "getUserMedia:response:allow"
+ );
+ let observerPromise2 = expectObserverCalled("recording-device-events");
+ await promiseMessage("ok", () =>
+ EventUtils.synthesizeMouseAtCenter(notification.button, {})
+ );
+ await observerPromise1;
+ await observerPromise2;
+ Assert.deepEqual(
+ await getMediaCaptureState(),
+ { audio: true, video: true },
+ "expected camera and microphone to be shared"
+ );
+ await indicator;
+ await checkSharingUI({ audio: true, video: true }, undefined, undefined, {
+ audio: { scope: SitePermissions.SCOPE_PERSISTENT },
+ video: { scope: SitePermissions.SCOPE_PERSISTENT },
+ });
+ await closeStream(true);
+
+ // Check that we get a prompt.
+ observerPromise = expectObserverCalled("getUserMedia:request");
+ promise = promisePopupNotificationShown("webRTC-shareDevices");
+ await promiseRequestDevice(true, true, "frame4");
+ await promise;
+ await observerPromise;
+
+ // The 'Remember this decision' checkbox is hidden.
+ notification = PopupNotifications.panel.firstElementChild;
+ checkbox = notification.checkbox;
+ ok(!!checkbox, "checkbox is present");
+ ok(checkbox.hidden, "checkbox is not visible");
+
+ observerPromise1 = expectObserverCalled("getUserMedia:response:deny");
+ observerPromise2 = expectObserverCalled("recording-window-ended");
+ await promiseMessage(permissionError, () => {
+ activateSecondaryAction(kActionDeny);
+ });
+
+ await observerPromise1;
+ await observerPromise2;
+ await checkNotSharing();
+
+ // Make sure we are not changing the scope and state of persistent
+ // permission
+ let { state, scope } = SitePermissions.getForPrincipal(
+ principal,
+ "camera",
+ browser
+ );
+ Assert.equal(state, SitePermissions.ALLOW);
+ Assert.equal(scope, SitePermissions.SCOPE_PERSISTENT);
+
+ ({ state, scope } = SitePermissions.getForPrincipal(
+ principal,
+ "microphone",
+ browser
+ ));
+ Assert.equal(state, SitePermissions.ALLOW);
+ Assert.equal(scope, SitePermissions.SCOPE_PERSISTENT);
+
+ PermissionTestUtils.remove(uri, "camera");
+ PermissionTestUtils.remove(uri, "microphone");
+ },
+ },
+];
+
+add_task(async function test() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["permissions.delegation.enabled", true],
+ ["dom.security.featurePolicy.header.enabled", true],
+ ["dom.security.featurePolicy.webidl.enabled", true],
+ ],
+ });
+
+ await runTests(gTests, {
+ relativeURI: "get_user_media_in_xorigin_frame.html",
+ });
+});