browser_auth_spoofing_protection.js (8063B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 ChromeUtils.defineESModuleGetters(this, { 7 UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.sys.mjs", 8 }); 9 10 let TEST_PATH = getRootDirectory(gTestPath).replace( 11 "chrome://mochitests/content", 12 "https://example.com" 13 ); 14 15 let TEST_PATH_AUTH = getRootDirectory(gTestPath).replace( 16 "chrome://mochitests/content", 17 "https://example.org" 18 ); 19 20 const CROSS_DOMAIN_URL = TEST_PATH + "redirect-crossDomain.html"; 21 22 const SAME_DOMAIN_URL = TEST_PATH + "redirect-sameDomain.html"; 23 24 const AUTH_URL = TEST_PATH_AUTH + "auth-route.sjs"; 25 26 /** 27 * Opens a new tab with a url that ether redirects us cross or same domain 28 * 29 * @param {boolean} doConfirmPrompt - true if we want to test the case when the user accepts the prompt, 30 * false if we want to test the case when the user cancels the prompt. 31 * @param {boolean} crossDomain - if true we will open a url that redirects us to a cross domain url, 32 * if false, we will open a url that redirects us to a same domain url 33 * @param {boolean} prefEnabled true will enable "privacy.authPromptSpoofingProtection", 34 * false will disable the pref 35 */ 36 async function trigger401AndHandle(doConfirmPrompt, crossDomain, prefEnabled) { 37 await SpecialPowers.pushPrefEnv({ 38 set: [["privacy.authPromptSpoofingProtection", prefEnabled]], 39 }); 40 let url = crossDomain ? CROSS_DOMAIN_URL : SAME_DOMAIN_URL; 41 let dialogShown = waitForDialog(doConfirmPrompt, crossDomain, prefEnabled); 42 await BrowserTestUtils.withNewTab(url, async function () { 43 await dialogShown; 44 }); 45 await new Promise(resolve => { 46 Services.clearData.deleteData( 47 Ci.nsIClearDataService.CLEAR_AUTH_CACHE, 48 resolve 49 ); 50 }); 51 } 52 53 async function waitForDialog(doConfirmPrompt, crossDomain, prefEnabled) { 54 await TestUtils.topicObserved("common-dialog-loaded"); 55 let dialog = gBrowser.getTabDialogBox(gBrowser.selectedBrowser) 56 ._tabDialogManager._topDialog; 57 let dialogDocument = dialog._frame.contentDocument; 58 if (crossDomain) { 59 if (prefEnabled) { 60 Assert.equal( 61 dialog._overlay.getAttribute("hideContent"), 62 "true", 63 "Dialog overlay hides the current sites content" 64 ); 65 Assert.equal( 66 window.gURLBar.value, 67 UrlbarTestUtils.trimURL(AUTH_URL), 68 "Correct location is provided by the prompt" 69 ); 70 Assert.equal( 71 window.gBrowser.selectedTab.label, 72 "example.org", 73 "Tab title is manipulated" 74 ); 75 // switch to another tab and make sure we dont mess up this new tabs url bar and tab title 76 let tab = await BrowserTestUtils.openNewForegroundTab( 77 gBrowser, 78 "https://example.org:443" 79 ); 80 Assert.equal( 81 window.gURLBar.value, 82 UrlbarTestUtils.trimURL("https://example.org"), 83 "No location is provided by the prompt, correct location is displayed" 84 ); 85 Assert.equal( 86 window.gBrowser.selectedTab.label, 87 "mochitest index /", 88 "Tab title is not manipulated" 89 ); 90 // switch back to our tab with the prompt and make sure the url bar state and tab title is still there 91 BrowserTestUtils.removeTab(tab); 92 Assert.equal( 93 window.gURLBar.value, 94 UrlbarTestUtils.trimURL(AUTH_URL), 95 "Correct location is provided by the prompt" 96 ); 97 Assert.equal( 98 window.gBrowser.selectedTab.label, 99 "example.org", 100 "Tab title is manipulated" 101 ); 102 // make sure a value that the user types in has a higher priority than our prompts location 103 gBrowser.selectedBrowser.userTypedValue = "user value"; 104 gURLBar.setURI(); 105 Assert.equal( 106 window.gURLBar.value, 107 "user value", 108 "User typed value is shown" 109 ); 110 // if the user clears the url bar we again fall back to the location of the prompt if we trigger setURI by a tab switch 111 gBrowser.selectedBrowser.userTypedValue = ""; 112 gURLBar.setURI({ dueToTabSwitch: true }); 113 Assert.equal( 114 window.gURLBar.value, 115 UrlbarTestUtils.trimURL(AUTH_URL), 116 "Correct location is provided by the prompt" 117 ); 118 // Cross domain and pref is not enabled 119 } else { 120 Assert.equal( 121 dialog._overlay.getAttribute("hideContent"), 122 null, 123 "Dialog overlay does not hide the current sites content" 124 ); 125 Assert.equal( 126 window.gURLBar.value, 127 UrlbarTestUtils.trimURL(CROSS_DOMAIN_URL), 128 "No location is provided by the prompt, correct location is displayed" 129 ); 130 Assert.equal( 131 window.gBrowser.selectedTab.label, 132 "example.com", 133 "Tab title is not manipulated" 134 ); 135 } 136 // same domain 137 } else { 138 Assert.equal( 139 dialog._overlay.getAttribute("hideContent"), 140 null, 141 "Dialog overlay does not hide the current sites content" 142 ); 143 Assert.equal( 144 window.gURLBar.value, 145 UrlbarTestUtils.trimURL(SAME_DOMAIN_URL), 146 "No location is provided by the prompt, correct location is displayed" 147 ); 148 Assert.equal( 149 window.gBrowser.selectedTab.label, 150 "example.com", 151 "Tab title is not manipulated" 152 ); 153 } 154 155 let onDialogClosed = BrowserTestUtils.waitForEvent( 156 window, 157 "DOMModalDialogClosed" 158 ); 159 if (doConfirmPrompt) { 160 dialogDocument.getElementById("loginTextbox").value = "guest"; 161 dialogDocument.getElementById("password1Textbox").value = "guest"; 162 dialogDocument.getElementById("commonDialog").acceptDialog(); 163 } else { 164 dialogDocument.getElementById("commonDialog").cancelDialog(); 165 } 166 167 // wait for the dialog to be closed to check that the URLBar state is reset 168 await onDialogClosed; 169 // Due to bug 1812014, the url bar will be clear if we have set its value to "" while the prompt was open 170 // so we trigger a tab switch again to have the uri displayed to be able to check its value 171 gURLBar.setURI({ dueToTabSwitch: true }); 172 Assert.equal( 173 window.gURLBar.value, 174 UrlbarTestUtils.trimURL(crossDomain ? CROSS_DOMAIN_URL : SAME_DOMAIN_URL), 175 "No location is provided by the prompt" 176 ); 177 Assert.equal( 178 window.gBrowser.selectedTab.label, 179 "example.com", 180 "Tab title is not manipulated" 181 ); 182 } 183 184 add_setup(async function () { 185 await SpecialPowers.pushPrefEnv({ 186 set: [["privacy.authPromptSpoofingProtection", true]], 187 }); 188 }); 189 190 /** 191 * Tests that the 401 auth spoofing mechanisms apply if the 401 is from a different base domain than the current sites, 192 * canceling the prompt 193 */ 194 add_task(async function testCrossDomainCancelPrefEnabled() { 195 await trigger401AndHandle(false, true, true); 196 }); 197 198 /** 199 * Tests that the 401 auth spoofing mechanisms apply if the 401 is from a different base domain than the current sites, 200 * accepting the prompt 201 */ 202 add_task(async function testCrossDomainAcceptPrefEnabled() { 203 await trigger401AndHandle(true, true, true); 204 }); 205 206 /** 207 * Tests that the 401 auth spoofing mechanisms do not apply if "privacy.authPromptSpoofingProtection" is not set to true 208 * canceling the prompt 209 */ 210 add_task(async function testCrossDomainCancelPrefDisabled() { 211 await trigger401AndHandle(false, true, false); 212 }); 213 214 /** 215 * Tests that the 401 auth spoofing mechanisms do not apply if "privacy.authPromptSpoofingProtection" is not set to true, 216 * accepting the prompt 217 */ 218 add_task(async function testCrossDomainAcceptPrefDisabled() { 219 await trigger401AndHandle(true, true, false); 220 }); 221 222 /** 223 * Tests that the 401 auth spoofing mechanisms are not triggered by a 401 within the same base domain as the current sites, 224 * canceling the prompt 225 */ 226 add_task(async function testSameDomainCancelPrefEnabled() { 227 await trigger401AndHandle(false, false, true); 228 }); 229 230 /** 231 * Tests that the 401 auth spoofing mechanisms are not triggered by a 401 within the same base domain as the current sites, 232 * accepting the prompt 233 */ 234 add_task(async function testSameDomainAcceptPrefEnabled() { 235 await trigger401AndHandle(true, false, true); 236 });