browser_dns_prefetch_link_header.js (9062B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // Test steps: 6 // 1. Load file_link_dns_prefetch.sjs 7 // 2.`<link rel="dns-prefetch" href="https://example.org">` is in 8 // the server-side sjs, so we will make the dns-request. 9 // 3. We verify that the dns request was made 10 11 const gDashboard = Cc["@mozilla.org/network/dashboard;1"].getService( 12 Ci.nsIDashboard 13 ); 14 15 ///////////////////////////////////////////////////////////////////////////// 16 // To observe DNS requests when running via the mochitest proxy we must first take a few steps: 17 // 18 // 1. Update the mochitest proxy pac file to include dns resolution. 19 // We do this by injecting "dnsResolve(host);" into the `FindProxyForURL()` pac function. 20 let existingPACScript = Services.prefs.getCharPref( 21 "network.proxy.autoconfig_url" 22 ); 23 24 let findProxyForURLFunction = "function FindProxyForURL(url, host){"; 25 let directDnsPacScript = existingPACScript.replace( 26 findProxyForURLFunction, 27 `${findProxyForURLFunction} 28 dnsResolve(host); 29 ` 30 ); 31 Services.prefs.setStringPref( 32 "network.proxy.autoconfig_url", 33 directDnsPacScript 34 ); 35 36 // 2. Ensure we don't disable dns prefetch despite using a proxy (this would otherwise happen after every request that the proxy completed) 37 Services.prefs.setBoolPref("network.dns.prefetch_via_proxy", true); 38 39 // 3. Make sure that HTTPS-First does not interfere with us loading HTTP tests 40 let initialHttpsFirst = Services.prefs.getBoolPref("dom.security.https_first"); 41 Services.prefs.setBoolPref("dom.security.https_first", false); 42 43 // 4. And finally enable dns prefetching via the private dns service api (generally disabled in mochitest proxy) 44 45 Services.dns.QueryInterface(Ci.nsPIDNSService).prefetchEnabled = true; 46 ///////////////////////////////////////////////////////////////////////////// 47 48 registerCleanupFunction(function () { 49 // Restore proxy pac and dns prefetch behaviour via proxy 50 Services.prefs.setCharPref("network.proxy.autoconfig_url", existingPACScript); 51 Services.prefs.clearUserPref("network.dns.prefetch_via_proxy"); 52 Services.prefs.setBoolPref("dom.security.https_first", initialHttpsFirst); 53 Services.dns.QueryInterface(Ci.nsPIDNSService).prefetchEnabled = false; 54 }); 55 56 async function isRecordFound(hostname) { 57 return new Promise(resolve => { 58 gDashboard.requestDNSInfo(function (data) { 59 let found = false; 60 for (let i = 0; i < data.entries.length; i++) { 61 if (data.entries[i].hostname == hostname) { 62 found = true; 63 break; 64 } 65 } 66 resolve(found); 67 }); 68 }); 69 } 70 71 let https_requestUrl = `https://example.com/browser/netwerk/test/browser/file_link_dns_prefetch.sjs`; 72 let http_requestUrl = `http://example.com/browser/netwerk/test/browser/file_link_dns_prefetch.sjs`; // eslint-disable-line @microsoft/sdl/no-insecure-url 73 74 add_setup(async function () { 75 await SpecialPowers.pushPrefEnv({ 76 set: [["test.wait300msAfterTabSwitch", true]], 77 }); 78 }); 79 80 // Test dns-prefetch on https 81 add_task(async function test_https_dns_prefetch() { 82 Services.dns.clearCache(true); 83 84 await BrowserTestUtils.withNewTab( 85 { 86 gBrowser, 87 url: https_requestUrl, 88 waitForLoad: true, 89 }, 90 async function () {} 91 ); 92 93 Assert.ok( 94 await TestUtils.waitForCondition(() => { 95 return isRecordFound("example.org"); 96 }), 97 "Record from link rel=dns-prefetch element should be found" 98 ); 99 Assert.ok(await isRecordFound("example.com"), "Host record should be found"); 100 }); 101 102 // Test dns-prefetch on http 103 add_task(async function test_http_dns_prefetch() { 104 Services.dns.clearCache(true); 105 106 await BrowserTestUtils.withNewTab( 107 { 108 gBrowser, 109 url: http_requestUrl, 110 waitForLoad: true, 111 }, 112 async function () {} 113 ); 114 115 Assert.ok( 116 await TestUtils.waitForCondition(() => { 117 return isRecordFound("example.org"); 118 }), 119 "Record from link rel=dns-prefetch element should be found" 120 ); 121 Assert.ok(await isRecordFound("example.com"), "Host record should be found"); 122 }); 123 124 // Test dns-prefetch on https with the feature disabled 125 add_task(async function test_https_dns_prefetch_disabled() { 126 Services.dns.clearCache(true); 127 128 // Disable the feature to verify that it will not prefetch 129 Services.prefs.setBoolPref("network.dns.disablePrefetchFromHTTPS", true); 130 131 await BrowserTestUtils.withNewTab( 132 { 133 gBrowser, 134 url: https_requestUrl, 135 waitForLoad: true, 136 }, 137 async function () {} 138 ); 139 140 Assert.ok(await isRecordFound("example.com"), "Host record should be found"); 141 Assert.ok( 142 !(await isRecordFound("example.org")), 143 "Record from link rel=dns-prefetch element should not be found with disablePrefetchFromHTTPS set" 144 ); 145 146 Services.prefs.clearUserPref("network.dns.disablePrefetchFromHTTPS"); 147 }); 148 149 // Test dns-prefetch on http with the feature disabled 150 add_task(async function test_http_dns_prefetch_disabled() { 151 Services.dns.clearCache(true); 152 153 // Disable the feature to verify, but this test is http, and so prefetch will execute 154 Services.prefs.setBoolPref("network.dns.disablePrefetchFromHTTPS", true); 155 156 await BrowserTestUtils.withNewTab( 157 { 158 gBrowser, 159 url: http_requestUrl, 160 waitForLoad: true, 161 }, 162 async function () {} 163 ); 164 165 Assert.ok( 166 await TestUtils.waitForCondition(() => { 167 return isRecordFound("example.org"); 168 }), 169 "Record from link rel=dns-prefetch element should be found on http page with disablePrefetchFromHTTPS set" 170 ); 171 Assert.ok(await isRecordFound("example.com"), "Host record should be found"); 172 173 Services.prefs.clearUserPref("network.dns.disablePrefetchFromHTTPS"); 174 }); 175 176 // Test if we speculatively prefetch dns for anchor elements on https documents 177 add_task(async function test_https_anchor_speculative_dns_prefetch() { 178 Services.dns.clearCache(true); 179 180 await BrowserTestUtils.withNewTab( 181 { 182 gBrowser, 183 url: https_requestUrl, 184 waitForLoad: true, 185 }, 186 async function () { 187 Assert.ok( 188 await isRecordFound("example.com"), 189 "Host record should be found" 190 ); 191 Assert.ok( 192 !(await isRecordFound("www.mozilla.org")), 193 "By default we do not speculatively prefetch dns for anchor elements on https documents" 194 ); 195 } 196 ); 197 198 // And enable the pref to verify that it works 199 Services.prefs.setBoolPref( 200 "dom.prefetch_dns_for_anchor_https_document", 201 true 202 ); 203 Services.dns.clearCache(true); 204 205 await BrowserTestUtils.withNewTab( 206 { 207 gBrowser, 208 url: https_requestUrl, 209 waitForLoad: true, 210 }, 211 async function () { 212 // The anchor element prefetchs are sent after pageload event; wait for them 213 Assert.ok( 214 await TestUtils.waitForCondition(() => { 215 return isRecordFound("www.mozilla.org"); 216 }), 217 "Speculatively prefetch dns for anchor elements on https documents" 218 ); 219 Assert.ok( 220 await isRecordFound("example.com"), 221 "Host record should be found" 222 ); 223 } 224 ); 225 226 Services.prefs.clearUserPref("dom.prefetch_dns_for_anchor_https_document"); 227 }); 228 229 // Test that we speculatively prefetch dns for anchor elements on http documents 230 add_task(async function test_http_anchor_speculative_dns_prefetch() { 231 Services.dns.clearCache(true); 232 233 await BrowserTestUtils.withNewTab( 234 { 235 gBrowser, 236 url: http_requestUrl, 237 waitForLoad: true, 238 }, 239 async function () { 240 Assert.ok( 241 await TestUtils.waitForCondition(() => { 242 return isRecordFound("example.org"); 243 }), 244 "Record from link rel=dns-prefetch element should be found" 245 ); 246 247 // The anchor element prefetchs are sent after pageload event; wait for them 248 Assert.ok( 249 await TestUtils.waitForCondition(() => { 250 return isRecordFound("www.mozilla.org"); 251 }), 252 "By default we speculatively prefetch dns for anchor elements on http documents" 253 ); 254 255 Assert.ok( 256 await isRecordFound("example.com"), 257 "Host record should be found" 258 ); 259 } 260 ); 261 262 // And disable the pref to verify that we no longer make the requests 263 Services.prefs.setBoolPref( 264 "dom.prefetch_dns_for_anchor_http_document", 265 false 266 ); 267 Services.dns.clearCache(true); 268 269 await BrowserTestUtils.withNewTab( 270 { 271 gBrowser, 272 url: http_requestUrl, 273 waitForLoad: true, 274 }, 275 async function () { 276 Assert.ok( 277 await TestUtils.waitForCondition(() => { 278 return isRecordFound("example.org"); 279 }), 280 "Record from link rel=dns-prefetch element should be found" 281 ); 282 Assert.ok( 283 !(await isRecordFound("www.mozilla.org")), 284 "We disabled speculative prefetch dns for anchor elements on http documents" 285 ); 286 Assert.ok( 287 await isRecordFound("example.com"), 288 "Host record should be found" 289 ); 290 } 291 ); 292 293 Services.prefs.clearUserPref("dom.prefetch_dns_for_anchor_http_document"); 294 });