/* 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."; var gTests = [ { desc: "getUserMedia audio+camera in frame 1", run: async function checkAudioVideoWhileLiveTracksExist_frame() { let observerPromise = expectObserverCalled("getUserMedia:request"); let promise = promisePopupNotificationShown("webRTC-shareDevices"); await promiseRequestDevice(true, true, "frame1"); await promise; await observerPromise; checkDeviceSelectors(["microphone", "camera"]); 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, video: true }, "expected camera and microphone to be shared" ); await indicator; await checkSharingUI({ video: true, audio: true }); info("gUM(audio+camera) in frame 2 should prompt"); observerPromise = expectObserverCalled("getUserMedia:request"); promise = promisePopupNotificationShown("webRTC-shareDevices"); await promiseRequestDevice(true, true, "frame2"); await promise; await observerPromise; checkDeviceSelectors(["microphone", "camera"]); observerPromise1 = expectObserverCalled("getUserMedia:response:deny"); observerPromise2 = expectObserverCalled("recording-window-ended"); await promiseMessage(permissionError, () => { activateSecondaryAction(kActionDeny); }); await observerPromise1; await observerPromise2; SitePermissions.removeFromPrincipal( null, "screen", gBrowser.selectedBrowser ); SitePermissions.removeFromPrincipal( null, "camera", gBrowser.selectedBrowser ); SitePermissions.removeFromPrincipal( null, "microphone", gBrowser.selectedBrowser ); // If there's an active audio+camera stream in frame 1, // gUM(audio+camera) in frame 1 returns a stream without prompting; let observerPromises = [ expectObserverCalled("getUserMedia:request"), expectObserverCalled("getUserMedia:response:allow"), expectObserverCalled("recording-device-events"), ]; promise = promiseMessage("ok"); await promiseRequestDevice(true, true, "frame1"); await promise; await observerPromises; await promiseNoPopupNotification("webRTC-shareDevices"); // close the stream await closeStream(false, "frame1"); }, }, { desc: "getUserMedia audio+camera in frame 1 - part II", run: async function checkAudioVideoWhileLiveTracksExist_frame_partII() { let observerPromise = expectObserverCalled("getUserMedia:request"); let promise = promisePopupNotificationShown("webRTC-shareDevices"); await promiseRequestDevice(true, true, "frame1"); await promise; await observerPromise; checkDeviceSelectors(["microphone", "camera"]); 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, video: true }, "expected camera and microphone to be shared" ); await indicator; await checkSharingUI({ video: true, audio: true }); // If there's an active audio+camera stream in frame 1, // gUM(audio+camera) in the top level window causes a prompt; observerPromise = expectObserverCalled("getUserMedia:request"); promise = promisePopupNotificationShown("webRTC-shareDevices"); await promiseRequestDevice(true, true); await promise; await observerPromise; checkDeviceSelectors(["microphone", "camera"]); observerPromise1 = expectObserverCalled("getUserMedia:response:deny"); observerPromise2 = expectObserverCalled("recording-window-ended"); await promiseMessage(permissionError, () => { activateSecondaryAction(kActionDeny); }); await observerPromise1; await observerPromise2; // close the stream await closeStream(false, "frame1"); SitePermissions.removeFromPrincipal( null, "screen", gBrowser.selectedBrowser ); SitePermissions.removeFromPrincipal( null, "camera", gBrowser.selectedBrowser ); SitePermissions.removeFromPrincipal( null, "microphone", gBrowser.selectedBrowser ); }, }, { desc: "getUserMedia audio+camera in frame 1 - reload", run: async function checkAudioVideoWhileLiveTracksExist_frame_reload() { let observerPromise = expectObserverCalled("getUserMedia:request"); let promise = promisePopupNotificationShown("webRTC-shareDevices"); await promiseRequestDevice(true, true, "frame1"); await promise; await observerPromise; checkDeviceSelectors(["microphone", "camera"]); 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, video: true }, "expected camera and microphone to be shared" ); await indicator; await checkSharingUI({ video: true, audio: true }); // reload frame 1 let observerPromises = [ expectObserverCalled("recording-device-stopped"), expectObserverCalled("recording-device-events"), expectObserverCalled("recording-window-ended"), ]; await promiseReloadFrame("frame1"); await Promise.all(observerPromises); await checkNotSharing(); // After the reload, // gUM(audio+camera) in frame 1 causes a prompt. observerPromise = expectObserverCalled("getUserMedia:request"); promise = promisePopupNotificationShown("webRTC-shareDevices"); await promiseRequestDevice(true, true, "frame1"); await promise; await observerPromise; checkDeviceSelectors(["microphone", "camera"]); observerPromise1 = expectObserverCalled("getUserMedia:response:deny"); observerPromise2 = expectObserverCalled("recording-window-ended"); await promiseMessage(permissionError, () => { activateSecondaryAction(kActionDeny); }); await observerPromise1; await observerPromise2; SitePermissions.removeFromPrincipal( null, "screen", gBrowser.selectedBrowser ); SitePermissions.removeFromPrincipal( null, "camera", gBrowser.selectedBrowser ); SitePermissions.removeFromPrincipal( null, "microphone", gBrowser.selectedBrowser ); }, }, { desc: "getUserMedia audio+camera at the top level window", run: async function checkAudioVideoWhileLiveTracksExist_topLevel() { // create an active audio+camera stream at the top level window let observerPromise = expectObserverCalled("getUserMedia:request"); let promise = promisePopupNotificationShown("webRTC-shareDevices"); await promiseRequestDevice(true, true); await promise; await observerPromise; checkDeviceSelectors(["microphone", "camera"]); 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, video: true }, "expected camera and microphone to be shared" ); await indicator; await checkSharingUI({ audio: true, video: true }); // If there's an active audio+camera stream at the top level window, // gUM(audio+camera) in frame 2 causes a prompt. observerPromise = expectObserverCalled("getUserMedia:request"); promise = promisePopupNotificationShown("webRTC-shareDevices"); await promiseRequestDevice(true, true, "frame2"); await promise; await observerPromise; checkDeviceSelectors(["microphone", "camera"]); observerPromise1 = expectObserverCalled("getUserMedia:response:deny"); observerPromise2 = expectObserverCalled("recording-window-ended"); await promiseMessage(permissionError, () => { activateSecondaryAction(kActionDeny); }); await observerPromise1; await observerPromise2; // close the stream await closeStream(); SitePermissions.removeFromPrincipal( null, "screen", gBrowser.selectedBrowser ); SitePermissions.removeFromPrincipal( null, "camera", gBrowser.selectedBrowser ); SitePermissions.removeFromPrincipal( null, "microphone", gBrowser.selectedBrowser ); }, }, ]; add_task(async function test() { await runTests(gTests, { relativeURI: "get_user_media_in_frame.html" }); });