head.js (10018B)
1 const REFERRER_URL_BASE = "/browser/browser/base/content/test/referrer/"; 2 const REFERRER_POLICYSERVER_URL = 3 "test1.example.com" + REFERRER_URL_BASE + "file_referrer_policyserver.sjs"; 4 const REFERRER_POLICYSERVER_URL_ATTRIBUTE = 5 "test1.example.com" + 6 REFERRER_URL_BASE + 7 "file_referrer_policyserver_attr.sjs"; 8 9 var gTestWindow = null; 10 var rounds = 0; 11 12 // We test that the UI code propagates three pieces of state - the referrer URI 13 // itself, the referrer policy, and the triggering principal. After that, we 14 // trust nsIWebNavigation to do the right thing with the info it's given, which 15 // is covered more exhaustively by dom/base/test/test_bug704320.html (which is 16 // a faster content-only test). So, here, we limit ourselves to cases that 17 // would break when the UI code drops either of these pieces; we don't try to 18 // duplicate the entire cross-product test in bug 704320 - that would be slow, 19 // especially when we're opening a new window for each case. 20 var _referrerTests = [ 21 // 1. Normal cases - no referrer policy, no special attributes. 22 // We expect a full referrer normally, and no referrer on downgrade. 23 { 24 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 25 fromScheme: "http://", 26 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 27 toScheme: "http://", 28 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 29 result: "http://test1.example.com/browser", // full referrer 30 }, 31 { 32 fromScheme: "https://", 33 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 34 toScheme: "http://", 35 result: "", // no referrer when downgrade 36 }, 37 // 2. Origin referrer policy - we expect an origin referrer, 38 // even on downgrade. But rel=noreferrer trumps this. 39 { 40 fromScheme: "https://", 41 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 42 toScheme: "http://", 43 policy: "origin", 44 result: "https://test1.example.com/", // origin, even on downgrade 45 }, 46 { 47 fromScheme: "https://", 48 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 49 toScheme: "http://", 50 policy: "origin", 51 rel: "noreferrer", 52 result: "", // rel=noreferrer trumps meta-referrer 53 }, 54 // 3. XXX: using no-referrer here until we support all attribute values (bug 1178337) 55 // Origin-when-cross-origin policy - this depends on the triggering 56 // principal. We expect full referrer for same-origin requests, 57 // and origin referrer for cross-origin requests. 58 { 59 fromScheme: "https://", 60 toScheme: "https://", 61 policy: "no-referrer", 62 result: "", // same origin https://test1.example.com/browser 63 }, 64 { 65 // eslint-disable-next-line @microsoft/sdl/no-insecure-url 66 fromScheme: "http://", 67 toScheme: "https://", 68 policy: "no-referrer", 69 result: "", // cross origin http://test1.example.com 70 }, 71 ]; 72 73 /** 74 * Returns the test object for a given test number. 75 * 76 * @param aTestNumber The test number - 0, 1, 2, ... 77 * @return The test object, or undefined if the number is out of range. 78 */ 79 function getReferrerTest(aTestNumber) { 80 return _referrerTests[aTestNumber]; 81 } 82 83 /** 84 * Returns shimmed test object for a given test number. 85 * 86 * @param aTestNumber The test number - 0, 1, 2, ... 87 * @return The test object with result hard-coded to "", 88 * or undefined if the number is out of range. 89 */ 90 function getRemovedReferrerTest(aTestNumber) { 91 let testCase = _referrerTests[aTestNumber]; 92 if (testCase) { 93 // We want all the referrer tests to fail! 94 testCase.result = ""; 95 } 96 97 return testCase; 98 } 99 100 /** 101 * Returns a brief summary of the test, for logging. 102 * 103 * @param aTestNumber The test number - 0, 1, 2... 104 * @return The test description. 105 */ 106 function getReferrerTestDescription(aTestNumber) { 107 let test = getReferrerTest(aTestNumber); 108 return ( 109 "policy=[" + 110 test.policy + 111 "] " + 112 "rel=[" + 113 test.rel + 114 "] " + 115 test.fromScheme + 116 " -> " + 117 test.toScheme 118 ); 119 } 120 121 /** 122 * Clicks the link. 123 * 124 * @param aWindow The window to click the link in. 125 * @param aLinkId The id of the link element. 126 * @param aOptions The options for synthesizeMouseAtCenter. 127 */ 128 function clickTheLink(aWindow, aLinkId, aOptions) { 129 return BrowserTestUtils.synthesizeMouseAtCenter( 130 "#" + aLinkId, 131 aOptions, 132 aWindow.gBrowser.selectedBrowser 133 ); 134 } 135 136 /** 137 * Extracts the referrer result from the target window. 138 * 139 * @param aWindow The window where the referrer target has loaded. 140 * @returns {Promise<string>} 141 * Resolves to the text of the (trimmed) referrer when extracted. 142 */ 143 function referrerResultExtracted(aWindow) { 144 return SpecialPowers.spawn(aWindow.gBrowser.selectedBrowser, [], function () { 145 return content.document.getElementById("testdiv").textContent; 146 }); 147 } 148 149 /** 150 * Waits for browser delayed startup to finish. 151 * 152 * @param aWindow The window to wait for. 153 * @returns {Promise<void>} 154 * Resolves when the window is loaded. 155 */ 156 function delayedStartupFinished(aWindow) { 157 return new Promise(function (resolve) { 158 Services.obs.addObserver(function observer(aSubject, aTopic) { 159 if (aWindow == aSubject) { 160 Services.obs.removeObserver(observer, aTopic); 161 resolve(); 162 } 163 }, "browser-delayed-startup-finished"); 164 }); 165 } 166 167 /** 168 * Waits for some (any) tab to load. The caller triggers the load. 169 * 170 * @param aWindow The window where to wait for a tab to load. 171 * @returns {Promise} 172 * Resolves to the tab once it's loaded. 173 */ 174 function someTabLoaded() { 175 return BrowserTestUtils.waitForNewTab(gTestWindow.gBrowser, null, true); 176 } 177 178 /** 179 * Waits for a new window to open and load. The caller triggers the open. 180 * 181 * @returns {Promise<Window>} 182 * Resolves to the new window once it's open and loaded. 183 */ 184 function newWindowOpened() { 185 return TestUtils.topicObserved("browser-delayed-startup-finished").then( 186 ([win]) => win 187 ); 188 } 189 190 /** 191 * Opens the context menu. 192 * 193 * @param aWindow The window to open the context menu in. 194 * @param aLinkId The id of the link to open the context menu on. 195 * @returns {Promise} 196 * Resolves with the menu popup when the context menu is open. 197 */ 198 function contextMenuOpened(aWindow, aLinkId) { 199 let popupShownPromise = BrowserTestUtils.waitForEvent( 200 aWindow.document, 201 "popupshown" 202 ); 203 // Simulate right-click. 204 clickTheLink(aWindow, aLinkId, { type: "contextmenu", button: 2 }); 205 return popupShownPromise.then(e => e.target); 206 } 207 208 /** 209 * Performs a context menu command. 210 * 211 * @param aWindow The window with the already open context menu. 212 * @param aMenu The menu popup to hide. 213 * @param aItemId The id of the menu item to activate. 214 */ 215 function doContextMenuCommand(aWindow, aMenu, aItemId) { 216 let command = aWindow.document.getElementById(aItemId); 217 command.doCommand(); 218 aMenu.hidePopup(); 219 } 220 221 /** 222 * Loads a single test case, i.e., a source url into gTestWindow. 223 * 224 * @param aTestNumber The test case number - 0, 1, 2... 225 * @returns {Promise<void>} 226 * Resolves when the source url for this test case is loaded. 227 */ 228 function referrerTestCaseLoaded(aTestNumber, aParams) { 229 let test = getReferrerTest(aTestNumber); 230 let server = 231 rounds == 0 232 ? REFERRER_POLICYSERVER_URL 233 : REFERRER_POLICYSERVER_URL_ATTRIBUTE; 234 let url = 235 test.fromScheme + 236 server + 237 "?scheme=" + 238 escape(test.toScheme) + 239 "&policy=" + 240 escape(test.policy || "") + 241 "&rel=" + 242 escape(test.rel || "") + 243 "&cross=" + 244 escape(test.cross || ""); 245 let browser = gTestWindow.gBrowser; 246 return BrowserTestUtils.openNewForegroundTab( 247 browser, 248 () => { 249 browser.selectedTab = BrowserTestUtils.addTab(browser, url, aParams); 250 }, 251 false, 252 true 253 ); 254 } 255 256 /** 257 * Checks the result of the referrer test, and moves on to the next test. 258 * 259 * @param aTestNumber The test number - 0, 1, 2, ... 260 * @param aNewWindow The new window where the referrer target opened, or null. 261 * @param aNewTab The new tab where the referrer target opened, or null. 262 * @param aStartTestCase The callback to start the next test, aTestNumber + 1. 263 */ 264 function checkReferrerAndStartNextTest( 265 aTestNumber, 266 aNewWindow, 267 aNewTab, 268 aStartTestCase, 269 aParams = {} 270 ) { 271 referrerResultExtracted(aNewWindow || gTestWindow).then(function (result) { 272 // Compare the actual result against the expected one. 273 let test = getReferrerTest(aTestNumber); 274 let desc = getReferrerTestDescription(aTestNumber); 275 is(result, test.result, desc); 276 277 // Clean up - close new tab / window, and then the source tab. 278 aNewTab && (aNewWindow || gTestWindow).gBrowser.removeTab(aNewTab); 279 aNewWindow && aNewWindow.close(); 280 is(gTestWindow.gBrowser.tabs.length, 2, "two tabs open"); 281 gTestWindow.gBrowser.removeTab(gTestWindow.gBrowser.tabs[1]); 282 283 // Move on to the next test. Or finish if we're done. 284 var nextTestNumber = aTestNumber + 1; 285 if (getReferrerTest(nextTestNumber)) { 286 referrerTestCaseLoaded(nextTestNumber, aParams).then(function () { 287 aStartTestCase(nextTestNumber); 288 }); 289 } else if (rounds == 0) { 290 nextTestNumber = 0; 291 rounds = 1; 292 referrerTestCaseLoaded(nextTestNumber, aParams).then(function () { 293 aStartTestCase(nextTestNumber); 294 }); 295 } else { 296 finish(); 297 } 298 }); 299 } 300 301 /** 302 * Fires up the complete referrer test. 303 * 304 * @param aStartTestCase The callback to start a single test case, called with 305 * the test number - 0, 1, 2... Needs to trigger the navigation from the source 306 * page, and call checkReferrerAndStartNextTest() when the target is loaded. 307 */ 308 function startReferrerTest(aStartTestCase, params = {}) { 309 waitForExplicitFinish(); 310 311 // Open the window where we'll load the source URLs. 312 gTestWindow = openDialog(location, "", "chrome,all,dialog=no", "about:blank"); 313 registerCleanupFunction(function () { 314 gTestWindow && gTestWindow.close(); 315 }); 316 317 // Load and start the first test. 318 delayedStartupFinished(gTestWindow).then(function () { 319 referrerTestCaseLoaded(0, params).then(function () { 320 aStartTestCase(0); 321 }); 322 }); 323 }