browser_global_mute_toggles.js (8970B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const TEST_ROOT = getRootDirectory(gTestPath).replace( 7 "chrome://mochitests/content/", 8 "https://example.com/" 9 ); 10 const TEST_PAGE = TEST_ROOT + "get_user_media.html"; 11 const MUTE_TOPICS = [ 12 "getUserMedia:muteVideo", 13 "getUserMedia:unmuteVideo", 14 "getUserMedia:muteAudio", 15 "getUserMedia:unmuteAudio", 16 ]; 17 18 add_setup(async function () { 19 let prefs = [ 20 [PREF_PERMISSION_FAKE, true], 21 [PREF_AUDIO_LOOPBACK, ""], 22 [PREF_VIDEO_LOOPBACK, ""], 23 [PREF_FAKE_STREAMS, true], 24 [PREF_FOCUS_SOURCE, false], 25 ["privacy.webrtc.globalMuteToggles", true], 26 ]; 27 await SpecialPowers.pushPrefEnv({ set: prefs }); 28 }); 29 30 /** 31 * Returns a Promise that resolves when the content process for 32 * <browser> fires the right observer notification based on the 33 * value of isMuted for the camera. 34 * 35 * Note: Callers must ensure that they first call 36 * BrowserTestUtils.startObservingTopics to monitor the mute and 37 * unmute observer notifications for this to work properly. 38 * 39 * @param {<xul:browser>} browser - The browser running in the content process 40 * to be monitored. 41 * @param {boolean} isMuted - True if the muted topic should be fired. 42 * @returns {Promise<void>} 43 * Resovles when the notification fires. 44 */ 45 function waitForCameraMuteState(browser, isMuted) { 46 let topic = isMuted ? "getUserMedia:muteVideo" : "getUserMedia:unmuteVideo"; 47 return BrowserTestUtils.contentTopicObserved(browser.browsingContext, topic); 48 } 49 50 /** 51 * Returns a Promise that resolves when the content process for 52 * <browser> fires the right observer notification based on the 53 * value of isMuted for the microphone. 54 * 55 * Note: Callers must ensure that they first call 56 * BrowserTestUtils.startObservingTopics to monitor the mute and 57 * unmute observer notifications for this to work properly. 58 * 59 * @param {<xul:browser>} browser - The browser running in the content process 60 * to be monitored. 61 * @param {boolean} isMuted - True if the muted topic should be fired. 62 * @returns {Promise<void>} 63 * Resolves when the notification fires. 64 */ 65 function waitForMicrophoneMuteState(browser, isMuted) { 66 let topic = isMuted ? "getUserMedia:muteAudio" : "getUserMedia:unmuteAudio"; 67 return BrowserTestUtils.contentTopicObserved(browser.browsingContext, topic); 68 } 69 70 /** 71 * Tests that the global mute toggles fire the right observer 72 * notifications in pre-existing content processes. 73 */ 74 add_task(async function test_notifications() { 75 await BrowserTestUtils.withNewTab(TEST_PAGE, async browser => { 76 let indicatorPromise = promiseIndicatorWindow(); 77 78 await shareDevices(browser, true /* camera */, true /* microphone */); 79 80 let indicator = await indicatorPromise; 81 let doc = indicator.document; 82 83 let microphoneMute = doc.getElementById("microphone-mute-toggle"); 84 let cameraMute = doc.getElementById("camera-mute-toggle"); 85 86 Assert.ok( 87 !microphoneMute.checked, 88 "Microphone toggle should not start checked." 89 ); 90 Assert.ok(!cameraMute.checked, "Camera toggle should not start checked."); 91 92 await BrowserTestUtils.startObservingTopics( 93 browser.browsingContext, 94 MUTE_TOPICS 95 ); 96 97 info("Muting microphone..."); 98 let microphoneMuted = waitForMicrophoneMuteState(browser, true); 99 microphoneMute.click(); 100 await microphoneMuted; 101 info("Microphone successfully muted."); 102 103 info("Muting camera..."); 104 let cameraMuted = waitForCameraMuteState(browser, true); 105 cameraMute.click(); 106 await cameraMuted; 107 info("Camera successfully muted."); 108 109 Assert.ok( 110 microphoneMute.checked, 111 "Microphone toggle should now be checked." 112 ); 113 Assert.ok(cameraMute.checked, "Camera toggle should now be checked."); 114 115 info("Unmuting microphone..."); 116 let microphoneUnmuted = waitForMicrophoneMuteState(browser, false); 117 microphoneMute.click(); 118 await microphoneUnmuted; 119 info("Microphone successfully unmuted."); 120 121 info("Unmuting camera..."); 122 let cameraUnmuted = waitForCameraMuteState(browser, false); 123 cameraMute.click(); 124 await cameraUnmuted; 125 info("Camera successfully unmuted."); 126 127 await BrowserTestUtils.stopObservingTopics( 128 browser.browsingContext, 129 MUTE_TOPICS 130 ); 131 }); 132 }); 133 134 /** 135 * Tests that if sharing stops while muted, and the indicator closes, 136 * then the mute state is reset. 137 */ 138 add_task(async function test_closing_indicator_resets_mute() { 139 await BrowserTestUtils.withNewTab(TEST_PAGE, async browser => { 140 let indicatorPromise = promiseIndicatorWindow(); 141 142 await shareDevices(browser, true /* camera */, true /* microphone */); 143 144 let indicator = await indicatorPromise; 145 let doc = indicator.document; 146 147 let microphoneMute = doc.getElementById("microphone-mute-toggle"); 148 let cameraMute = doc.getElementById("camera-mute-toggle"); 149 150 Assert.ok( 151 !microphoneMute.checked, 152 "Microphone toggle should not start checked." 153 ); 154 Assert.ok(!cameraMute.checked, "Camera toggle should not start checked."); 155 156 await BrowserTestUtils.startObservingTopics( 157 browser.browsingContext, 158 MUTE_TOPICS 159 ); 160 161 info("Muting microphone..."); 162 let microphoneMuted = waitForMicrophoneMuteState(browser, true); 163 microphoneMute.click(); 164 await microphoneMuted; 165 info("Microphone successfully muted."); 166 167 info("Muting camera..."); 168 let cameraMuted = waitForCameraMuteState(browser, true); 169 cameraMute.click(); 170 await cameraMuted; 171 info("Camera successfully muted."); 172 173 Assert.ok( 174 microphoneMute.checked, 175 "Microphone toggle should now be checked." 176 ); 177 Assert.ok(cameraMute.checked, "Camera toggle should now be checked."); 178 179 let allUnmuted = Promise.all([ 180 waitForMicrophoneMuteState(browser, false), 181 waitForCameraMuteState(browser, false), 182 ]); 183 184 await closeStream(); 185 await allUnmuted; 186 187 await BrowserTestUtils.stopObservingTopics( 188 browser.browsingContext, 189 MUTE_TOPICS 190 ); 191 }); 192 }); 193 194 /** 195 * Test that if the global mute state is set, then newly created 196 * content processes also have their tracks muted after sending 197 * a getUserMedia request. 198 */ 199 add_task(async function test_new_processes() { 200 let tab1 = await BrowserTestUtils.openNewForegroundTab({ 201 gBrowser, 202 url: TEST_PAGE, 203 }); 204 let browser1 = tab1.linkedBrowser; 205 206 let indicatorPromise = promiseIndicatorWindow(); 207 208 await shareDevices(browser1, true /* camera */, true /* microphone */); 209 210 let indicator = await indicatorPromise; 211 let doc = indicator.document; 212 213 let microphoneMute = doc.getElementById("microphone-mute-toggle"); 214 let cameraMute = doc.getElementById("camera-mute-toggle"); 215 216 Assert.ok( 217 !microphoneMute.checked, 218 "Microphone toggle should not start checked." 219 ); 220 Assert.ok(!cameraMute.checked, "Camera toggle should not start checked."); 221 222 await BrowserTestUtils.startObservingTopics( 223 browser1.browsingContext, 224 MUTE_TOPICS 225 ); 226 227 info("Muting microphone..."); 228 let microphoneMuted = waitForMicrophoneMuteState(browser1, true); 229 microphoneMute.click(); 230 await microphoneMuted; 231 info("Microphone successfully muted."); 232 233 info("Muting camera..."); 234 let cameraMuted = waitForCameraMuteState(browser1, true); 235 cameraMute.click(); 236 await cameraMuted; 237 info("Camera successfully muted."); 238 239 // We'll make sure a new process is being launched by observing 240 // for the ipc:content-created notification. 241 let processLaunched = TestUtils.topicObserved("ipc:content-created"); 242 243 let tab2 = await BrowserTestUtils.openNewForegroundTab({ 244 gBrowser, 245 url: TEST_PAGE, 246 forceNewProcess: true, 247 }); 248 let browser2 = tab2.linkedBrowser; 249 250 await processLaunched; 251 252 await BrowserTestUtils.startObservingTopics( 253 browser2.browsingContext, 254 MUTE_TOPICS 255 ); 256 257 let microphoneMuted2 = waitForMicrophoneMuteState(browser2, true); 258 let cameraMuted2 = waitForCameraMuteState(browser2, true); 259 info("Sharing the microphone and camera from a new process."); 260 await shareDevices(browser2, true /* camera */, true /* microphone */); 261 await Promise.all([microphoneMuted2, cameraMuted2]); 262 263 info("Unmuting microphone..."); 264 let microphoneUnmuted = Promise.all([ 265 waitForMicrophoneMuteState(browser1, false), 266 waitForMicrophoneMuteState(browser2, false), 267 ]); 268 microphoneMute.click(); 269 await microphoneUnmuted; 270 info("Microphone successfully unmuted."); 271 272 info("Unmuting camera..."); 273 let cameraUnmuted = Promise.all([ 274 waitForCameraMuteState(browser1, false), 275 waitForCameraMuteState(browser2, false), 276 ]); 277 cameraMute.click(); 278 await cameraUnmuted; 279 info("Camera successfully unmuted."); 280 281 await BrowserTestUtils.stopObservingTopics( 282 browser1.browsingContext, 283 MUTE_TOPICS 284 ); 285 286 await BrowserTestUtils.stopObservingTopics( 287 browser2.browsingContext, 288 MUTE_TOPICS 289 ); 290 291 BrowserTestUtils.removeTab(tab2); 292 BrowserTestUtils.removeTab(tab1); 293 });