test_cacheflags.js (11014B)
1 "use strict"; 2 3 const { HttpServer } = ChromeUtils.importESModule( 4 "resource://testing-common/httpd.sys.mjs" 5 ); 6 7 var httpserver = new HttpServer(); 8 httpserver.start(-1); 9 10 // Need to randomize, because apparently no one clears our cache 11 var suffix = Math.random(); 12 var httpBase = "http://localhost:" + httpserver.identity.primaryPort; 13 var shortexpPath = "/shortexp" + suffix; 14 var longexpPath = "/longexp/" + suffix; 15 var longexp2Path = "/longexp/2/" + suffix; 16 var nocachePath = "/nocache" + suffix; 17 var nostorePath = "/nostore" + suffix; 18 var test410Path = "/test410" + suffix; 19 var test404Path = "/test404" + suffix; 20 21 var PrivateBrowsingLoadContext = Cu.createPrivateLoadContext(); 22 23 function make_channel(url, flags, usePrivateBrowsing) { 24 var securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; 25 26 var uri = Services.io.newURI(url); 27 var principal = Services.scriptSecurityManager.createContentPrincipal(uri, { 28 privateBrowsingId: usePrivateBrowsing ? 1 : 0, 29 }); 30 31 var req = NetUtil.newChannel({ 32 uri, 33 loadingPrincipal: principal, 34 securityFlags, 35 contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER, 36 }); 37 38 req.loadFlags = flags; 39 if (usePrivateBrowsing) { 40 req.notificationCallbacks = PrivateBrowsingLoadContext; 41 } 42 return req; 43 } 44 45 function Test( 46 path, 47 flags, 48 expectSuccess, 49 readFromCache, 50 hitServer, 51 usePrivateBrowsing /* defaults to false */ 52 ) { 53 this.path = path; 54 this.flags = flags; 55 this.expectSuccess = expectSuccess; 56 this.readFromCache = readFromCache; 57 this.hitServer = hitServer; 58 this.usePrivateBrowsing = usePrivateBrowsing; 59 } 60 61 Test.prototype = { 62 flags: 0, 63 expectSuccess: true, 64 readFromCache: false, 65 hitServer: true, 66 usePrivateBrowsing: false, 67 _buffer: "", 68 _isFromCache: false, 69 70 QueryInterface: ChromeUtils.generateQI([ 71 "nsIStreamListener", 72 "nsIRequestObserver", 73 ]), 74 75 onStartRequest(request) { 76 var cachingChannel = request.QueryInterface(Ci.nsICacheInfoChannel); 77 this._isFromCache = request.isPending() && cachingChannel.isFromCache(); 78 }, 79 80 onDataAvailable(request, stream, offset, count) { 81 this._buffer = this._buffer.concat(read_stream(stream, count)); 82 }, 83 84 onStopRequest(request, status) { 85 Assert.equal(Components.isSuccessCode(status), this.expectSuccess); 86 Assert.equal(this._isFromCache, this.readFromCache); 87 Assert.equal(gHitServer, this.hitServer); 88 89 do_timeout(0, run_next_test); 90 }, 91 92 run() { 93 dump( 94 "Running:" + 95 "\n " + 96 this.path + 97 "\n " + 98 this.flags + 99 "\n " + 100 this.expectSuccess + 101 "\n " + 102 this.readFromCache + 103 "\n " + 104 this.hitServer + 105 "\n" 106 ); 107 gHitServer = false; 108 var channel = make_channel(this.path, this.flags, this.usePrivateBrowsing); 109 channel.asyncOpen(this); 110 }, 111 }; 112 113 var gHitServer = false; 114 115 var gTests = [ 116 new Test( 117 httpBase + shortexpPath, 118 0, 119 true, // expect success 120 false, // read from cache 121 true, // hit server 122 true 123 ), // USE PRIVATE BROWSING, so not cached for later requests 124 new Test( 125 httpBase + shortexpPath, 126 0, 127 true, // expect success 128 false, // read from cache 129 true 130 ), // hit server 131 new Test( 132 httpBase + shortexpPath, 133 0, 134 true, // expect success 135 true, // read from cache 136 true 137 ), // hit server 138 new Test( 139 httpBase + shortexpPath, 140 Ci.nsIRequest.LOAD_BYPASS_CACHE, 141 true, // expect success 142 false, // read from cache 143 true 144 ), // hit server 145 new Test( 146 httpBase + shortexpPath, 147 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE, 148 false, // expect success 149 false, // read from cache 150 false 151 ), // hit server 152 new Test( 153 httpBase + shortexpPath, 154 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | Ci.nsIRequest.VALIDATE_NEVER, 155 true, // expect success 156 true, // read from cache 157 false 158 ), // hit server 159 new Test( 160 httpBase + shortexpPath, 161 Ci.nsIRequest.LOAD_FROM_CACHE, 162 true, // expect success 163 true, // read from cache 164 false 165 ), // hit server 166 167 new Test( 168 httpBase + longexpPath, 169 0, 170 true, // expect success 171 false, // read from cache 172 true 173 ), // hit server 174 new Test( 175 httpBase + longexpPath, 176 0, 177 true, // expect success 178 true, // read from cache 179 false 180 ), // hit server 181 new Test( 182 httpBase + longexpPath, 183 Ci.nsIRequest.LOAD_BYPASS_CACHE, 184 true, // expect success 185 false, // read from cache 186 true 187 ), // hit server 188 new Test( 189 httpBase + longexpPath, 190 Ci.nsIRequest.VALIDATE_ALWAYS, 191 true, // expect success 192 true, // read from cache 193 true 194 ), // hit server 195 new Test( 196 httpBase + longexpPath, 197 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE, 198 true, // expect success 199 true, // read from cache 200 false 201 ), // hit server 202 new Test( 203 httpBase + longexpPath, 204 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | Ci.nsIRequest.VALIDATE_NEVER, 205 true, // expect success 206 true, // read from cache 207 false 208 ), // hit server 209 new Test( 210 httpBase + longexpPath, 211 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | Ci.nsIRequest.VALIDATE_ALWAYS, 212 false, // expect success 213 false, // read from cache 214 false 215 ), // hit server 216 new Test( 217 httpBase + longexpPath, 218 Ci.nsIRequest.LOAD_FROM_CACHE, 219 true, // expect success 220 true, // read from cache 221 false 222 ), // hit server 223 224 new Test( 225 httpBase + longexp2Path, 226 0, 227 true, // expect success 228 false, // read from cache 229 true 230 ), // hit server 231 new Test( 232 httpBase + longexp2Path, 233 0, 234 true, // expect success 235 true, // read from cache 236 false 237 ), // hit server 238 239 new Test( 240 httpBase + nocachePath, 241 0, 242 true, // expect success 243 false, // read from cache 244 true 245 ), // hit server 246 new Test( 247 httpBase + nocachePath, 248 0, 249 true, // expect success 250 true, // read from cache 251 true 252 ), // hit server 253 new Test( 254 httpBase + nocachePath, 255 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE, 256 false, // expect success 257 false, // read from cache 258 false 259 ), // hit server 260 261 // CACHE2: mayhemer - entry is doomed... I think the logic is wrong, we should not doom them 262 // as they are not valid, but take them as they need to reval 263 /* 264 new Test(httpBase + nocachePath, Ci.nsIRequest.LOAD_FROM_CACHE, 265 true, // expect success 266 true, // read from cache 267 false), // hit server 268 */ 269 270 // LOAD_ONLY_FROM_CACHE would normally fail (because no-cache forces 271 // a validation), but VALIDATE_NEVER should override that. 272 new Test( 273 httpBase + nocachePath, 274 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | Ci.nsIRequest.VALIDATE_NEVER, 275 true, // expect success 276 true, // read from cache 277 false 278 ), // hit server 279 280 // ... however, no-cache over ssl should act like no-store and force 281 // a validation (and therefore failure) even if VALIDATE_NEVER is 282 // set. 283 /* XXX bug 466524: We can't currently start an ssl server in xpcshell tests, 284 so this test is currently disabled. 285 new Test(httpsBase + nocachePath, 286 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | 287 Ci.nsIRequest.VALIDATE_NEVER, 288 false, // expect success 289 false, // read from cache 290 false) // hit server 291 */ 292 293 new Test( 294 httpBase + nostorePath, 295 0, 296 true, // expect success 297 false, // read from cache 298 true 299 ), // hit server 300 new Test( 301 httpBase + nostorePath, 302 0, 303 true, // expect success 304 false, // read from cache 305 true 306 ), // hit server 307 new Test( 308 httpBase + nostorePath, 309 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE, 310 false, // expect success 311 false, // read from cache 312 false 313 ), // hit server 314 new Test( 315 httpBase + nostorePath, 316 Ci.nsIRequest.LOAD_FROM_CACHE, 317 true, // expect success 318 true, // read from cache 319 false 320 ), // hit server 321 // no-store should force the validation (and therefore failure, with 322 // LOAD_ONLY_FROM_CACHE) even if VALIDATE_NEVER is set. 323 new Test( 324 httpBase + nostorePath, 325 Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | Ci.nsIRequest.VALIDATE_NEVER, 326 false, // expect success 327 false, // read from cache 328 false 329 ), // hit server 330 331 new Test( 332 httpBase + test410Path, 333 0, 334 true, // expect success 335 false, // read from cache 336 true 337 ), // hit server 338 new Test( 339 httpBase + test410Path, 340 0, 341 true, // expect success 342 true, // read from cache 343 false 344 ), // hit server 345 346 new Test( 347 httpBase + test404Path, 348 0, 349 true, // expect success 350 false, // read from cache 351 true 352 ), // hit server 353 new Test( 354 httpBase + test404Path, 355 0, 356 true, // expect success 357 false, // read from cache 358 true 359 ), // hit server 360 ]; 361 362 function run_next_test() { 363 if (!gTests.length) { 364 httpserver.stop(do_test_finished); 365 return; 366 } 367 368 var test = gTests.shift(); 369 test.run(); 370 } 371 372 function handler(httpStatus, metadata, response) { 373 gHitServer = true; 374 let etag; 375 try { 376 etag = metadata.getHeader("If-None-Match"); 377 } catch (ex) { 378 etag = ""; 379 } 380 if (etag == "testtag") { 381 // Allow using the cached data 382 response.setStatusLine(metadata.httpVersion, 304, "Not Modified"); 383 } else { 384 response.setStatusLine(metadata.httpVersion, httpStatus, "Useless Phrase"); 385 response.setHeader("Content-Type", "text/plain", false); 386 response.setHeader("ETag", "testtag", false); 387 const body = "data"; 388 response.bodyOutputStream.write(body, body.length); 389 } 390 } 391 392 function nocache_handler(metadata, response) { 393 response.setHeader("Cache-Control", "no-cache", false); 394 handler(200, metadata, response); 395 } 396 397 function nostore_handler(metadata, response) { 398 response.setHeader("Cache-Control", "no-store", false); 399 handler(200, metadata, response); 400 } 401 402 function test410_handler(metadata, response) { 403 handler(410, metadata, response); 404 } 405 406 function test404_handler(metadata, response) { 407 handler(404, metadata, response); 408 } 409 410 function shortexp_handler(metadata, response) { 411 response.setHeader("Cache-Control", "max-age=0", false); 412 handler(200, metadata, response); 413 } 414 415 function longexp_handler(metadata, response) { 416 response.setHeader("Cache-Control", "max-age=10000", false); 417 handler(200, metadata, response); 418 } 419 420 // test spaces around max-age value token 421 function longexp2_handler(metadata, response) { 422 response.setHeader("Cache-Control", "max-age = 10000", false); 423 handler(200, metadata, response); 424 } 425 426 function run_test() { 427 httpserver.registerPathHandler(shortexpPath, shortexp_handler); 428 httpserver.registerPathHandler(longexpPath, longexp_handler); 429 httpserver.registerPathHandler(longexp2Path, longexp2_handler); 430 httpserver.registerPathHandler(nocachePath, nocache_handler); 431 httpserver.registerPathHandler(nostorePath, nostore_handler); 432 httpserver.registerPathHandler(test410Path, test410_handler); 433 httpserver.registerPathHandler(test404Path, test404_handler); 434 435 run_next_test(); 436 do_test_pending(); 437 }