browser_refreshBlocker.js (6770B)
1 "use strict"; 2 3 const META_PAGE = 4 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 5 "http://example.org/browser/browser/base/content/test/general/refresh_meta.sjs"; 6 const HEADER_PAGE = 7 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 8 "http://example.org/browser/browser/base/content/test/general/refresh_header.sjs"; 9 const TARGET_PAGE = 10 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 11 "http://example.org/browser/browser/base/content/test/general/dummy_page.html"; 12 const PREF = "accessibility.blockautorefresh"; 13 14 /** 15 * Goes into the content, and simulates a meta-refresh header at a very 16 * low level, and checks to see if it was blocked. This will always cancel 17 * the refresh, regardless of whether or not the refresh was blocked. 18 * 19 * @param browser (<xul:browser>) 20 * The browser to test for refreshing. 21 * @param expectRefresh (bool) 22 * Whether or not we expect the refresh attempt to succeed. 23 * @returns Promise 24 */ 25 async function attemptFakeRefresh(browser, expectRefresh) { 26 await SpecialPowers.spawn( 27 browser, 28 [expectRefresh], 29 async function (contentExpectRefresh) { 30 let URI = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI; 31 let refresher = docShell.QueryInterface(Ci.nsIRefreshURI); 32 refresher.refreshURI(URI, null, 0); 33 34 Assert.equal( 35 refresher.refreshPending, 36 contentExpectRefresh, 37 "Got the right refreshPending state" 38 ); 39 40 if (refresher.refreshPending) { 41 // Cancel the pending refresh 42 refresher.cancelRefreshURITimers(); 43 } 44 45 // The RefreshBlocker will wait until onLocationChange has 46 // been fired before it will show any notifications (see bug 47 // 1246291), so we cause this to occur manually here. 48 content.location = URI.spec + "#foo"; 49 } 50 ); 51 } 52 53 /** 54 * Tests that we can enable the blocking pref and block a refresh 55 * from occurring while showing a notification bar. Also tests that 56 * when we disable the pref, that refreshes can go through again. 57 */ 58 add_task(async function test_can_enable_and_block() { 59 await BrowserTestUtils.withNewTab( 60 { 61 gBrowser, 62 url: TARGET_PAGE, 63 }, 64 async function (browser) { 65 // By default, we should be able to reload the page. 66 await attemptFakeRefresh(browser, true); 67 68 await pushPrefs(["accessibility.blockautorefresh", true]); 69 70 let notificationPromise = BrowserTestUtils.waitForNotificationBar( 71 gBrowser, 72 browser, 73 "refresh-blocked" 74 ); 75 76 await attemptFakeRefresh(browser, false); 77 78 await notificationPromise; 79 80 await pushPrefs(["accessibility.blockautorefresh", false]); 81 82 // Page reloads should go through again. 83 await attemptFakeRefresh(browser, true); 84 } 85 ); 86 }); 87 88 /** 89 * Attempts a "real" refresh by opening a tab, and then sending it to 90 * an SJS page that will attempt to cause a refresh. This will also pass 91 * a delay amount to the SJS page. The refresh should be blocked, and 92 * the notification should be shown. Once shown, the "Allow" button will 93 * be clicked, and the refresh will go through. Finally, the helper will 94 * close the tab and resolve the Promise. 95 * 96 * @param refreshPage (string) 97 * The SJS page to use. Use META_PAGE for the <meta> tag refresh 98 * case. Use HEADER_PAGE for the HTTP header case. 99 * @param delay (int) 100 * The amount, in ms, for the page to wait before attempting the 101 * refresh. 102 * 103 * @returns Promise 104 */ 105 async function testRealRefresh(refreshPage, delay) { 106 await BrowserTestUtils.withNewTab( 107 { 108 gBrowser, 109 url: "about:blank", 110 }, 111 async function (browser) { 112 await pushPrefs(["accessibility.blockautorefresh", true]); 113 114 BrowserTestUtils.startLoadingURIString( 115 browser, 116 refreshPage + "?p=" + TARGET_PAGE + "&d=" + delay 117 ); 118 await BrowserTestUtils.browserLoaded(browser); 119 120 // Once browserLoaded resolves, all nsIWebProgressListener callbacks 121 // should have fired, so the notification should be visible. 122 let notificationBox = gBrowser.getNotificationBox(browser); 123 let notification = notificationBox.currentNotification; 124 125 ok(notification, "Notification should be visible"); 126 is( 127 notification.getAttribute("value"), 128 "refresh-blocked", 129 "Should be showing the right notification" 130 ); 131 132 // Then click the button to allow the refresh. 133 let buttons = notification.buttonContainer.querySelectorAll( 134 ".notification-button" 135 ); 136 is(buttons.length, 1, "Should have one button."); 137 138 // Prepare a Promise that should resolve when the refresh goes through 139 let refreshPromise = BrowserTestUtils.browserLoaded(browser); 140 buttons[0].click(); 141 142 await refreshPromise; 143 } 144 ); 145 } 146 147 /** 148 * Tests the meta-tag case for both short and longer delay times. 149 */ 150 add_task(async function test_can_allow_refresh() { 151 await testRealRefresh(META_PAGE, 0); 152 await testRealRefresh(META_PAGE, 100); 153 await testRealRefresh(META_PAGE, 500); 154 }); 155 156 /** 157 * Tests that when a HTTP header case for both short and longer 158 * delay times. 159 */ 160 add_task(async function test_can_block_refresh_from_header() { 161 await testRealRefresh(HEADER_PAGE, 0); 162 await testRealRefresh(HEADER_PAGE, 100); 163 await testRealRefresh(HEADER_PAGE, 500); 164 }); 165 166 /** 167 * Tests that we can update a notification when multiple reload/redirect 168 * attempts happen. 169 */ 170 add_task(async function test_can_update_notification() { 171 await BrowserTestUtils.withNewTab( 172 { 173 gBrowser, 174 url: "about:blank", 175 }, 176 async function (browser) { 177 await pushPrefs(["accessibility.blockautorefresh", true]); 178 179 // First, attempt a redirect 180 BrowserTestUtils.startLoadingURIString( 181 browser, 182 META_PAGE + "?d=0&p=" + TARGET_PAGE 183 ); 184 await BrowserTestUtils.browserLoaded(browser); 185 186 // Once browserLoaded resolves, all nsIWebProgressListener callbacks 187 // should have fired, so the notification should be visible. 188 let notificationBox = gBrowser.getNotificationBox(browser); 189 let notification = notificationBox.currentNotification; 190 let [redirectLabel, refreshLabel] = await document.l10n.formatValues([ 191 { id: "refresh-blocked-redirect-label" }, 192 { id: "refresh-blocked-refresh-label" }, 193 ]); 194 195 is( 196 notification.messageText.textContent.trim(), 197 redirectLabel, 198 "Should be showing the redirect message" 199 ); 200 201 // Next, attempt a refresh 202 await attemptFakeRefresh(browser, false); 203 204 is( 205 notification.messageText.textContent.trim(), 206 refreshLabel, 207 "Should be showing the refresh message" 208 ); 209 } 210 ); 211 });