browser_bug1415918_beforeunload_options.js (4843B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 const TEST_PATH = getRootDirectory(gTestPath).replace( 5 "chrome://mochitests/content", 6 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 7 "http://example.com" 8 ); 9 10 const { PromptTestUtils } = ChromeUtils.importESModule( 11 "resource://testing-common/PromptTestUtils.sys.mjs" 12 ); 13 14 SimpleTest.requestFlakyTimeout("Needs to test a timeout"); 15 16 function delay(msec) { 17 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout 18 return new Promise(resolve => setTimeout(resolve, msec)); 19 } 20 21 function allowNextNavigation(browser) { 22 return PromptTestUtils.handleNextPrompt( 23 browser, 24 { modalType: Services.prompt.MODAL_TYPE_CONTENT, promptType: "confirmEx" }, 25 { buttonNumClick: 0 } 26 ); 27 } 28 29 function cancelNextNavigation(browser) { 30 return PromptTestUtils.handleNextPrompt( 31 browser, 32 { modalType: Services.prompt.MODAL_TYPE_CONTENT, promptType: "confirmEx" }, 33 { buttonNumClick: 1 } 34 ); 35 } 36 37 add_task(async function test() { 38 await SpecialPowers.pushPrefEnv({ 39 set: [["dom.require_user_interaction_for_beforeunload", false]], 40 }); 41 42 const permitUnloadTimeout = Services.prefs.getIntPref( 43 "dom.beforeunload_timeout_ms" 44 ); 45 46 let url = TEST_PATH + "dummy_page.html"; 47 let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url); 48 let browser = tab.linkedBrowser; 49 50 await SpecialPowers.spawn(browser.browsingContext, [], () => { 51 content.addEventListener("beforeunload", event => { 52 event.preventDefault(); 53 }); 54 }); 55 56 /* 57 * Check condition where beforeunload handlers request a prompt. 58 */ 59 60 // Prompt is shown, user clicks OK. 61 62 let promptShownPromise = allowNextNavigation(browser); 63 ok(browser.permitUnload().permitUnload, "permit unload should be true"); 64 await promptShownPromise; 65 66 // Prompt is shown, user clicks CANCEL. 67 promptShownPromise = cancelNextNavigation(browser); 68 ok(!browser.permitUnload().permitUnload, "permit unload should be false"); 69 await promptShownPromise; 70 71 // Prompt is not shown, don't permit unload. 72 let promptShown = false; 73 let shownCallback = () => { 74 promptShown = true; 75 }; 76 77 browser.addEventListener("DOMWillOpenModalDialog", shownCallback); 78 ok( 79 !browser.permitUnload("dontUnload").permitUnload, 80 "permit unload should be false" 81 ); 82 ok(!promptShown, "prompt should not have been displayed"); 83 84 // Prompt is not shown, permit unload. 85 promptShown = false; 86 ok( 87 browser.permitUnload("unload").permitUnload, 88 "permit unload should be true" 89 ); 90 ok(!promptShown, "prompt should not have been displayed"); 91 browser.removeEventListener("DOMWillOpenModalDialog", shownCallback); 92 93 promptShownPromise = PromptTestUtils.waitForPrompt(browser, { 94 modalType: Services.prompt.MODAL_TYPE_CONTENT, 95 promptType: "confirmEx", 96 }); 97 98 let promptDismissed = false; 99 let closedCallback = () => { 100 promptDismissed = true; 101 }; 102 103 browser.addEventListener("DOMModalDialogClosed", closedCallback); 104 105 let promise = browser.asyncPermitUnload(); 106 107 let promiseResolved = false; 108 promise.then(() => { 109 promiseResolved = true; 110 }); 111 112 let dialog = await promptShownPromise; 113 ok(!promiseResolved, "Should not have resolved promise yet"); 114 115 await delay(permitUnloadTimeout * 1.5); 116 117 ok(!promptDismissed, "Should not have dismissed prompt yet"); 118 ok(!promiseResolved, "Should not have resolved promise yet"); 119 120 await PromptTestUtils.handlePrompt(dialog, { buttonNumClick: 1 }); 121 122 let { permitUnload } = await promise; 123 ok(promptDismissed, "Should have dismissed prompt"); 124 ok(!permitUnload, "Should not have permitted unload"); 125 126 browser.removeEventListener("DOMModalDialogClosed", closedCallback); 127 128 promptShownPromise = allowNextNavigation(browser); 129 130 /* 131 * Check condition where no one requests a prompt. In all cases, 132 * permitUnload should be true, and all handlers fired. 133 */ 134 url += "?1"; 135 BrowserTestUtils.startLoadingURIString(browser, url); 136 await BrowserTestUtils.browserLoaded(browser, false, url); 137 await promptShownPromise; 138 139 promptShown = false; 140 browser.addEventListener("DOMWillOpenModalDialog", shownCallback); 141 142 ok(browser.permitUnload().permitUnload, "permit unload should be true"); 143 ok(!promptShown, "prompt should not have been displayed"); 144 145 promptShown = false; 146 ok( 147 browser.permitUnload("dontUnload").permitUnload, 148 "permit unload should be true" 149 ); 150 ok(!promptShown, "prompt should not have been displayed"); 151 152 promptShown = false; 153 ok( 154 browser.permitUnload("unload").permitUnload, 155 "permit unload should be true" 156 ); 157 ok(!promptShown, "prompt should not have been displayed"); 158 159 browser.removeEventListener("DOMWillOpenModalDialog", shownCallback); 160 161 await BrowserTestUtils.removeTab(tab, { skipPermitUnload: true }); 162 });