browser_prompt_close_event.js (10077B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const BUILDER_URL = "https://example.com/document-builder.sjs?html="; 7 8 const BEFOREUNLOAD_MARKUP = ` 9 <html> 10 <head> 11 <script> 12 window.onbeforeunload = function() { 13 return true; 14 }; 15 </script> 16 </head> 17 <body>TEST PAGE</body> 18 </html> 19 `; 20 const BEFOREUNLOAD_URL = BUILDER_URL + encodeURI(BEFOREUNLOAD_MARKUP); 21 22 /** 23 * Execute the provided script content by generating a dynamic script tag and 24 * inserting it in the page for the provided browser. 25 * 26 * @param {string} script 27 * The script to execute. 28 * @param {Browser} browser 29 * The browser element where the script has to be to executed. 30 * Defaults to a current selected browser. 31 * @returns {Promise} 32 * A promise that resolves when the script node was added and removed from 33 * the content page. 34 */ 35 function createScriptNode(script, browser = gBrowser.selectedBrowser) { 36 return SpecialPowers.spawn(browser, [script], function (_script) { 37 const scriptTag = content.document.createElement("script"); 38 scriptTag.append(content.document.createTextNode(_script)); 39 content.document.body.append(scriptTag); 40 }); 41 } 42 43 add_task(async function test_close_prompt_event_detail_prompt_types() { 44 for (const promptType of ["alert", "confirm", "prompt"]) { 45 info(`test prompt of type "${promptType}"`); 46 47 const closed = BrowserTestUtils.waitForEvent( 48 window, 49 "DOMModalDialogClosed" 50 ); 51 52 const promptPromise = BrowserTestUtils.promiseAlertDialogOpen(); 53 await createScriptNode(`setTimeout(() => window.${promptType}('test'))`); 54 const promptWin = await promptPromise; 55 56 info("accepting prompt with default value."); 57 promptWin.document.querySelector("dialog").acceptDialog(); 58 59 const closedEvent = await closed; 60 61 is( 62 closedEvent.detail.promptType, 63 promptType, 64 "Received correct `promptType` value in the event detail" 65 ); 66 } 67 }); 68 69 add_task(async function test_close_prompt_event_detail_beforeunload() { 70 await SpecialPowers.pushPrefEnv({ 71 set: [["dom.require_user_interaction_for_beforeunload", false]], 72 }); 73 74 for (const leavePage of [false, true]) { 75 info(`Test with leavePage=${leavePage}`); 76 const closed = BrowserTestUtils.waitForEvent( 77 window, 78 "DOMModalDialogClosed" 79 ); 80 81 await BrowserTestUtils.withNewTab( 82 BEFOREUNLOAD_URL, 83 async function (browser) { 84 let dialogPromise = BrowserTestUtils.promiseAlertDialogOpen(); 85 BrowserTestUtils.startLoadingURIString(browser, "about:blank"); 86 const dialogWin = await dialogPromise; 87 88 if (leavePage) { 89 dialogWin.document.querySelector("dialog").acceptDialog(); 90 } else { 91 dialogWin.document.querySelector("dialog").cancelDialog(); 92 } 93 94 const closedEvent = await closed; 95 is( 96 closedEvent.detail.areLeaving, 97 leavePage, 98 "Received correct `areLeaving` value in the event detail" 99 ); 100 is( 101 closedEvent.detail.promptType, 102 "beforeunload", 103 "Received correct `promptType` value in the event detail" 104 ); 105 is( 106 closedEvent.detail.owningBrowsingContext, 107 browser.browsingContext, 108 "Received correct `owningBrowsingContext` value in the event detail" 109 ); 110 111 if (leavePage) { 112 await BrowserTestUtils.browserLoaded(browser, false, "about:blank"); 113 } 114 115 // Now we need to get rid of the handler to avoid the prompt coming up 116 // when trying to close the tab when we exit `withNewTab`. 117 await SpecialPowers.spawn(browser, [], function () { 118 content.window.onbeforeunload = null; 119 }); 120 } 121 ); 122 } 123 }); 124 125 add_task( 126 async function test_close_prompt_event_detail_accepted_with_default_value() { 127 const closed = BrowserTestUtils.waitForEvent( 128 window, 129 "DOMModalDialogClosed" 130 ); 131 132 const promptPromise = BrowserTestUtils.promiseAlertDialogOpen(); 133 134 const defaultValue = "Default value"; 135 await createScriptNode( 136 `setTimeout(() => window.prompt('Enter your name:', '${defaultValue}'))` 137 ); 138 const promptWin = await promptPromise; 139 140 info("accepting prompt with default value."); 141 promptWin.document.querySelector("dialog").acceptDialog(); 142 143 const closedEvent = await closed; 144 145 is( 146 closedEvent.detail.areLeaving, 147 true, 148 "Received correct `areLeaving` value in the event detail" 149 ); 150 is( 151 closedEvent.detail.promptType, 152 "prompt", 153 "Received correct `promptType` value in the event detail" 154 ); 155 is( 156 closedEvent.detail.value, 157 defaultValue, 158 "Received correct `value` value in the event detail" 159 ); 160 is( 161 closedEvent.detail.owningBrowsingContext, 162 gBrowser.selectedBrowser.browsingContext, 163 "Received correct `owningBrowsingContext` value in the event detail" 164 ); 165 } 166 ); 167 168 add_task( 169 async function test_close_prompt_event_detail_accepted_with_amended_default_value() { 170 const closed = BrowserTestUtils.waitForEvent( 171 window, 172 "DOMModalDialogClosed" 173 ); 174 175 const promptPromise = BrowserTestUtils.promiseAlertDialogOpen(); 176 177 const defaultValue = "Default value"; 178 await createScriptNode( 179 `setTimeout(() => window.prompt('Enter your name:', '${defaultValue}'))` 180 ); 181 const promptWin = await promptPromise; 182 183 const amendedValue = "Test"; 184 promptWin.document.getElementById("loginTextbox").value = amendedValue; 185 186 info("accepting prompt with amended value."); 187 promptWin.document.querySelector("dialog").acceptDialog(); 188 189 const closedEvent = await closed; 190 191 is( 192 closedEvent.detail.areLeaving, 193 true, 194 "Received correct `areLeaving` value in the event detail" 195 ); 196 is( 197 closedEvent.detail.promptType, 198 "prompt", 199 "Received correct `promptType` value in the event detail" 200 ); 201 is( 202 closedEvent.detail.value, 203 amendedValue, 204 "Received correct `value` value in the event detail" 205 ); 206 is( 207 closedEvent.detail.owningBrowsingContext, 208 gBrowser.selectedBrowser.browsingContext, 209 "Received correct `owningBrowsingContext` value in the event detail" 210 ); 211 } 212 ); 213 214 add_task( 215 async function test_close_prompt_event_detail_dismissed_with_default_value() { 216 const closed = BrowserTestUtils.waitForEvent( 217 window, 218 "DOMModalDialogClosed" 219 ); 220 221 const promptPromise = BrowserTestUtils.promiseAlertDialogOpen(); 222 223 const defaultValue = "Default value"; 224 await createScriptNode( 225 `setTimeout(() => window.prompt('Enter your name:', '${defaultValue}'))` 226 ); 227 const promptWin = await promptPromise; 228 229 info("Dismissing prompt with default value."); 230 promptWin.document.querySelector("dialog").cancelDialog(); 231 232 const closedEvent = await closed; 233 234 is( 235 closedEvent.detail.areLeaving, 236 false, 237 "Received correct `areLeaving` value in the event detail" 238 ); 239 is( 240 closedEvent.detail.promptType, 241 "prompt", 242 "Received correct `promptType` value in the event detail" 243 ); 244 is( 245 closedEvent.detail.value, 246 null, 247 "Received correct `value` value in the event detail" 248 ); 249 is( 250 closedEvent.detail.owningBrowsingContext, 251 gBrowser.selectedBrowser.browsingContext, 252 "Received correct `owningBrowsingContext` value in the event detail" 253 ); 254 } 255 ); 256 257 add_task( 258 async function test_close_prompt_event_detail_dismissed_with_amended_default_value() { 259 const closed = BrowserTestUtils.waitForEvent( 260 window, 261 "DOMModalDialogClosed" 262 ); 263 264 const promptPromise = BrowserTestUtils.promiseAlertDialogOpen(); 265 266 const defaultValue = "Default value"; 267 await createScriptNode( 268 `setTimeout(() => window.prompt('Enter your name:', '${defaultValue}'))` 269 ); 270 const promptWin = await promptPromise; 271 272 const amendedValue = "Test"; 273 promptWin.document.getElementById("loginTextbox").value = amendedValue; 274 275 info("Dismissing prompt with amended value."); 276 promptWin.document.querySelector("dialog").cancelDialog(); 277 278 const closedEvent = await closed; 279 280 is( 281 closedEvent.detail.areLeaving, 282 false, 283 "Received correct `areLeaving` value in the event detail" 284 ); 285 is( 286 closedEvent.detail.promptType, 287 "prompt", 288 "Received correct `promptType` value in the event detail" 289 ); 290 is( 291 closedEvent.detail.value, 292 null, 293 "Received correct `value` value in the event detail" 294 ); 295 is( 296 closedEvent.detail.owningBrowsingContext, 297 gBrowser.selectedBrowser.browsingContext, 298 "Received correct `owningBrowsingContext` value in the event detail" 299 ); 300 } 301 ); 302 303 add_task(async function test_close_prompt_event_detail_in_iframe() { 304 const IFRAME_HTML = ` 305 <!doctype html> 306 <html> 307 <head> 308 <meta charset=utf8> 309 </head> 310 <body> 311 <h1>Iframe</h1> 312 </body> 313 </html>`; 314 315 const PAGE_WITH_IFRAME = ` 316 <html> 317 <head> 318 </head> 319 <body> 320 <iframe src='${BUILDER_URL + encodeURI(IFRAME_HTML)}'></iframe> 321 </body> 322 </html> 323 `; 324 325 await BrowserTestUtils.withNewTab( 326 BUILDER_URL + encodeURI(PAGE_WITH_IFRAME), 327 async function (browser) { 328 const iframeBrowsingContext = browser.browsingContext.children[0]; 329 330 const closed = BrowserTestUtils.waitForEvent( 331 window, 332 "DOMModalDialogClosed" 333 ); 334 335 const promptPromise = BrowserTestUtils.promiseAlertDialogOpen(); 336 await createScriptNode( 337 `setTimeout(() => window.alert('test'))`, 338 iframeBrowsingContext 339 ); 340 const promptWin = await promptPromise; 341 342 info("accepting prompt with default value."); 343 promptWin.document.querySelector("dialog").acceptDialog(); 344 345 const closedEvent = await closed; 346 347 is( 348 closedEvent.detail.owningBrowsingContext, 349 iframeBrowsingContext, 350 "Received correct `owningBrowsingContext` value in the event detail" 351 ); 352 } 353 ); 354 });