summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame_chain.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame_chain.js')
-rw-r--r--browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame_chain.js251
1 files changed, 251 insertions, 0 deletions
diff --git a/browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame_chain.js b/browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame_chain.js
new file mode 100644
index 0000000000..ad398994f0
--- /dev/null
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_in_xorigin_frame_chain.js
@@ -0,0 +1,251 @@
+/* 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;
+
+function expectObserverCalledAncestor(aTopic, browsingContext) {
+ if (!gMultiProcessBrowser) {
+ return expectObserverCalledInProcess(aTopic);
+ }
+
+ return BrowserTestUtils.contentTopicObserved(browsingContext, aTopic);
+}
+
+function enableObserverVerificationAncestor(browsingContext) {
+ // Skip these checks in single process mode as it isn't worth implementing it.
+ if (!gMultiProcessBrowser) {
+ return Promise.resolve();
+ }
+
+ return BrowserTestUtils.startObservingTopics(browsingContext, observerTopics);
+}
+
+function disableObserverVerificationAncestor(browsingContextt) {
+ if (!gMultiProcessBrowser) {
+ return Promise.resolve();
+ }
+
+ return BrowserTestUtils.stopObservingTopics(
+ browsingContextt,
+ observerTopics
+ ).catch(reason => {
+ ok(false, "Failed " + reason);
+ });
+}
+
+function promiseRequestDeviceAncestor(
+ aRequestAudio,
+ aRequestVideo,
+ aType,
+ aBrowser,
+ aBadDevice = false
+) {
+ info("requesting devices");
+ return SpecialPowers.spawn(
+ aBrowser,
+ [{ aRequestAudio, aRequestVideo, aType, aBadDevice }],
+ async function (args) {
+ let global =
+ content.wrappedJSObject.document.getElementById("frame4").contentWindow;
+ global.requestDevice(
+ args.aRequestAudio,
+ args.aRequestVideo,
+ args.aType,
+ args.aBadDevice
+ );
+ }
+ );
+}
+
+async function closeStreamAncestor(browser) {
+ let observerPromises = [];
+ observerPromises.push(
+ expectObserverCalledAncestor("recording-device-events", browser)
+ );
+ observerPromises.push(
+ expectObserverCalledAncestor("recording-window-ended", browser)
+ );
+
+ info("closing the stream");
+ await SpecialPowers.spawn(browser, [], async () => {
+ let global =
+ content.wrappedJSObject.document.getElementById("frame4").contentWindow;
+ global.closeStream();
+ });
+
+ await Promise.all(observerPromises);
+
+ await assertWebRTCIndicatorStatus(null);
+}
+
+var gTests = [
+ {
+ desc: "getUserMedia use persistent permissions from first party if third party is explicitly trusted",
+ skipObserverVerification: true,
+ run: async function checkPermissionsAncestorChain() {
+ async function checkPermission(aPermission, aRequestType, 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;
+ }
+ const iframeAncestor = await SpecialPowers.spawn(
+ gBrowser.selectedBrowser,
+ [],
+ () => {
+ return content.document.getElementById("frameAncestor")
+ .browsingContext;
+ }
+ );
+
+ if (aExpect == PromptResult.PROMPT) {
+ // Check that we get a prompt.
+ const observerPromise = expectObserverCalledAncestor(
+ "getUserMedia:request",
+ iframeAncestor
+ );
+ const promise = promisePopupNotificationShown("webRTC-shareDevices");
+
+ await promiseRequestDeviceAncestor(
+ audio,
+ video,
+ screen,
+ iframeAncestor
+ );
+ 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"
+ );
+ const observerPromise1 = expectObserverCalledAncestor(
+ "getUserMedia:response:deny",
+ iframeAncestor
+ );
+ const observerPromise2 = expectObserverCalledAncestor(
+ "recording-window-ended",
+ iframeAncestor
+ );
+ // Deny the request to cleanup...
+ activateSecondaryAction(kActionDeny);
+ await observerPromise1;
+ await observerPromise2;
+ let browser = gBrowser.selectedBrowser;
+ SitePermissions.removeFromPrincipal(null, aRequestType, browser);
+ } else if (aExpect == PromptResult.ALLOW) {
+ const observerPromise = expectObserverCalledAncestor(
+ "getUserMedia:request",
+ iframeAncestor
+ );
+ const observerPromise1 = expectObserverCalledAncestor(
+ "getUserMedia:response:allow",
+ iframeAncestor
+ );
+ const observerPromise2 = expectObserverCalledAncestor(
+ "recording-device-events",
+ iframeAncestor
+ );
+ await promiseRequestDeviceAncestor(
+ audio,
+ video,
+ screen,
+ iframeAncestor
+ );
+ 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 closeStreamAncestor(iframeAncestor);
+ } else if (aExpect == PromptResult.DENY) {
+ const observerPromise = expectObserverCalledAncestor(
+ "recording-window-ended",
+ iframeAncestor
+ );
+ await promiseRequestDeviceAncestor(
+ audio,
+ video,
+ screen,
+ iframeAncestor
+ );
+ await observerPromise;
+ }
+
+ PermissionTestUtils.remove(uri, aRequestType);
+ }
+
+ await checkPermission(Perms.PROMPT_ACTION, "camera", PromptResult.PROMPT);
+ await checkPermission(Perms.DENY_ACTION, "camera", PromptResult.DENY);
+ await checkPermission(Perms.ALLOW_ACTION, "camera", PromptResult.ALLOW);
+
+ await checkPermission(
+ Perms.PROMPT_ACTION,
+ "microphone",
+ PromptResult.PROMPT
+ );
+ await checkPermission(Perms.DENY_ACTION, "microphone", PromptResult.DENY);
+ await checkPermission(
+ Perms.ALLOW_ACTION,
+ "microphone",
+ PromptResult.ALLOW
+ );
+
+ await checkPermission(Perms.PROMPT_ACTION, "screen", PromptResult.PROMPT);
+ await checkPermission(Perms.DENY_ACTION, "screen", PromptResult.DENY);
+ // Always prompt screen sharing
+ await checkPermission(Perms.ALLOW_ACTION, "screen", PromptResult.PROMPT);
+ },
+ },
+];
+
+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_ancestor.html",
+ });
+});