browser_notification_silencing.js (6868B)
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 12 /** 13 * Tests that the screen / window sharing permission popup offers the ability 14 * for users to silence DOM notifications while sharing. 15 */ 16 17 /** 18 * Helper function that exercises a specific browser to test whether or not the 19 * user can silence notifications via the display sharing permission panel. 20 * 21 * First, we ensure that notification silencing is disabled by default. Then, we 22 * request screen sharing from the browser, and check the checkbox that 23 * silences notifications. Once screen sharing is established, then we ensure 24 * that notification silencing is enabled. Then we stop sharing, and ensure that 25 * notification silencing is disabled again. 26 * 27 * @param {<xul:browser>} aBrowser - The window to run the test on. This browser 28 * should have TEST_PAGE loaded. 29 * @returns {Promise<void>} 30 * Resolves when the test on the browser is complete. 31 */ 32 async function testNotificationSilencing(aBrowser) { 33 let hasIndicator = Services.wm 34 .getEnumerator("Browser:WebRTCGlobalIndicator") 35 .hasMoreElements(); 36 37 let window = aBrowser.ownerGlobal; 38 39 let alertsService = Cc["@mozilla.org/alerts-service;1"] 40 .getService(Ci.nsIAlertsService) 41 .QueryInterface(Ci.nsIAlertsDoNotDisturb); 42 Assert.ok(alertsService, "Alerts Service implements nsIAlertsDoNotDisturb"); 43 Assert.ok( 44 !alertsService.suppressForScreenSharing, 45 "Should not be silencing notifications to start." 46 ); 47 48 let observerPromise = expectObserverCalled( 49 "getUserMedia:request", 50 1, 51 aBrowser 52 ); 53 let promise = promisePopupNotificationShown( 54 "webRTC-shareDevices", 55 null, 56 window 57 ); 58 let indicatorPromise = hasIndicator 59 ? Promise.resolve() 60 : promiseIndicatorWindow(); 61 await promiseRequestDevice(false, true, null, "screen", aBrowser); 62 await promise; 63 await observerPromise; 64 65 checkDeviceSelectors(["screen"], window); 66 67 let document = window.document; 68 69 // Select one of the windows / screens. It doesn't really matter which. 70 let menulist = document.getElementById("webRTC-selectWindow-menulist"); 71 menulist.getItemAtIndex(menulist.itemCount - 1).doCommand(); 72 73 let notification = window.PopupNotifications.panel.firstElementChild; 74 Assert.ok( 75 notification.hasAttribute("warninghidden"), 76 "Notification silencing warning message is hidden by default" 77 ); 78 79 let checkbox = notification.checkbox; 80 Assert.ok(!!checkbox, "Notification silencing checkbox is present"); 81 Assert.ok(!checkbox.checked, "checkbox is not checked by default"); 82 checkbox.click(); 83 Assert.ok(checkbox.checked, "checkbox now checked"); 84 // The orginal behaviour of the checkbox disabled the Allow button. Let's 85 // make sure we're not still doing that. 86 Assert.ok(!notification.button.disabled, "Allow button is not disabled"); 87 Assert.ok( 88 notification.hasAttribute("warninghidden"), 89 "No warning message is shown" 90 ); 91 92 let observerPromise1 = expectObserverCalled( 93 "getUserMedia:response:allow", 94 1, 95 aBrowser 96 ); 97 let observerPromise2 = expectObserverCalled( 98 "recording-device-events", 99 1, 100 aBrowser 101 ); 102 await promiseMessage( 103 "ok", 104 () => { 105 notification.button.click(); 106 }, 107 1, 108 aBrowser 109 ); 110 await observerPromise1; 111 await observerPromise2; 112 let indicator = await indicatorPromise; 113 114 Assert.ok( 115 alertsService.suppressForScreenSharing, 116 "Should now be silencing notifications" 117 ); 118 119 let indicatorClosedPromise = hasIndicator 120 ? Promise.resolve() 121 : BrowserTestUtils.domWindowClosed(indicator); 122 123 await stopSharing("screen", true, aBrowser, window); 124 await indicatorClosedPromise; 125 126 Assert.ok( 127 !alertsService.suppressForScreenSharing, 128 "Should no longer be silencing notifications" 129 ); 130 } 131 132 add_setup(async function () { 133 // Set prefs so that permissions prompts are shown and loopback devices 134 // are not used. To test the chrome we want prompts to be shown, and 135 // these tests are flakey when using loopback devices (though it would 136 // be desirable to make them work with loopback in future). See bug 1643711. 137 let prefs = [ 138 [PREF_PERMISSION_FAKE, true], 139 [PREF_AUDIO_LOOPBACK, ""], 140 [PREF_VIDEO_LOOPBACK, ""], 141 [PREF_FAKE_STREAMS, true], 142 [PREF_FOCUS_SOURCE, false], 143 ]; 144 145 await SpecialPowers.pushPrefEnv({ set: prefs }); 146 }); 147 148 /** 149 * Tests notification silencing in a normal browser window. 150 */ 151 add_task(async function testNormalWindow() { 152 await BrowserTestUtils.withNewTab( 153 { 154 gBrowser, 155 url: TEST_PAGE, 156 }, 157 async browser => { 158 await testNotificationSilencing(browser); 159 } 160 ); 161 }); 162 163 /** 164 * Tests notification silencing in a private browser window. 165 */ 166 add_task(async function testPrivateWindow() { 167 let privateWindow = await BrowserTestUtils.openNewBrowserWindow({ 168 private: true, 169 }); 170 await BrowserTestUtils.withNewTab( 171 { 172 gBrowser: privateWindow.gBrowser, 173 url: TEST_PAGE, 174 }, 175 async browser => { 176 await testNotificationSilencing(browser); 177 } 178 ); 179 180 await BrowserTestUtils.closeWindow(privateWindow); 181 }); 182 183 /** 184 * Tests notification silencing when sharing a screen while already 185 * sharing the microphone. Alone ensures that if we stop sharing the 186 * screen, but continue sharing the microphone, that notification 187 * silencing ends. 188 */ 189 add_task(async function testWhileSharingMic() { 190 await BrowserTestUtils.withNewTab( 191 { 192 gBrowser, 193 url: TEST_PAGE, 194 }, 195 async browser => { 196 let promise = promisePopupNotificationShown("webRTC-shareDevices"); 197 let observerPromise = expectObserverCalled("getUserMedia:request"); 198 await promiseRequestDevice(true, true); 199 await promise; 200 await observerPromise; 201 202 let indicatorPromise = promiseIndicatorWindow(); 203 let observerPromise1 = expectObserverCalled( 204 "getUserMedia:response:allow" 205 ); 206 let observerPromise2 = expectObserverCalled("recording-device-events"); 207 208 promise = promiseMessage("ok", () => { 209 PopupNotifications.panel.firstElementChild.button.click(); 210 }); 211 await observerPromise1; 212 await observerPromise2; 213 await promise; 214 215 Assert.deepEqual( 216 await getMediaCaptureState(), 217 { audio: true, video: true }, 218 "expected camera and microphone to be shared" 219 ); 220 221 let indicator = await indicatorPromise; 222 await checkSharingUI({ audio: true, video: true }); 223 224 await testNotificationSilencing(browser); 225 226 let indicatorClosedPromise = BrowserTestUtils.domWindowClosed(indicator); 227 await closeStream(); 228 await indicatorClosedPromise; 229 } 230 ); 231 });