michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: michael@0: var httpserver = new HttpServer(); michael@0: httpserver.start(-1); michael@0: michael@0: // Need to randomize, because apparently no one clears our cache michael@0: var suffix = Math.random(); michael@0: var httpBase = "http://localhost:" + httpserver.identity.primaryPort; michael@0: var httpsBase = "http://localhost:4445"; michael@0: var shortexpPath = "/shortexp" + suffix; michael@0: var longexpPath = "/longexp/" + suffix; michael@0: var longexp2Path = "/longexp/2/" + suffix; michael@0: var nocachePath = "/nocache" + suffix; michael@0: var nostorePath = "/nostore" + suffix; michael@0: michael@0: // We attach this to channel when we want to test Private Browsing mode michael@0: function LoadContext(usePrivateBrowsing) { michael@0: this.usePrivateBrowsing = usePrivateBrowsing; michael@0: } michael@0: michael@0: LoadContext.prototype = { michael@0: usePrivateBrowsing: false, michael@0: // don't bother defining rest of nsILoadContext fields: don't need 'em michael@0: michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsILoadContext)) michael@0: return this; michael@0: throw Cr.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: getInterface: function(iid) { michael@0: if (iid.equals(Ci.nsILoadContext)) michael@0: return this; michael@0: throw Cr.NS_ERROR_NO_INTERFACE; michael@0: } michael@0: }; michael@0: michael@0: PrivateBrowsingLoadContext = new LoadContext(true); michael@0: michael@0: function make_channel(url, flags, usePrivateBrowsing) { michael@0: var ios = Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: var req = ios.newChannel(url, null, null); michael@0: req.loadFlags = flags; michael@0: if (usePrivateBrowsing) { michael@0: req.notificationCallbacks = PrivateBrowsingLoadContext; michael@0: } michael@0: return req; michael@0: } michael@0: michael@0: function Test(path, flags, expectSuccess, readFromCache, hitServer, michael@0: usePrivateBrowsing /* defaults to false */) { michael@0: this.path = path; michael@0: this.flags = flags; michael@0: this.expectSuccess = expectSuccess; michael@0: this.readFromCache = readFromCache; michael@0: this.hitServer = hitServer; michael@0: this.usePrivateBrowsing = usePrivateBrowsing; michael@0: } michael@0: michael@0: Test.prototype = { michael@0: flags: 0, michael@0: expectSuccess: true, michael@0: readFromCache: false, michael@0: hitServer: true, michael@0: usePrivateBrowsing: false, michael@0: _buffer: "", michael@0: _isFromCache: false, michael@0: michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Components.interfaces.nsIStreamListener) || michael@0: iid.equals(Components.interfaces.nsIRequestObserver) || michael@0: iid.equals(Components.interfaces.nsISupports)) michael@0: return this; michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: onStartRequest: function(request, context) { michael@0: var cachingChannel = request.QueryInterface(Ci.nsICacheInfoChannel); michael@0: this._isFromCache = request.isPending() && cachingChannel.isFromCache(); michael@0: }, michael@0: michael@0: onDataAvailable: function(request, context, stream, offset, count) { michael@0: this._buffer = this._buffer.concat(read_stream(stream, count)); michael@0: }, michael@0: michael@0: onStopRequest: function(request, context, status) { michael@0: do_check_eq(Components.isSuccessCode(status), this.expectSuccess); michael@0: do_check_eq(this._isFromCache, this.readFromCache); michael@0: do_check_eq(gHitServer, this.hitServer); michael@0: michael@0: do_timeout(0, run_next_test); michael@0: }, michael@0: michael@0: run: function() { michael@0: dump("Running:" + michael@0: "\n " + this.path + michael@0: "\n " + this.flags + michael@0: "\n " + this.expectSuccess + michael@0: "\n " + this.readFromCache + michael@0: "\n " + this.hitServer + "\n"); michael@0: gHitServer = false; michael@0: var channel = make_channel(this.path, this.flags, this.usePrivateBrowsing); michael@0: channel.asyncOpen(this, null); michael@0: } michael@0: }; michael@0: michael@0: var gHitServer = false; michael@0: michael@0: var gTests = [ michael@0: michael@0: new Test(httpBase + shortexpPath, 0, michael@0: true, // expect success michael@0: false, // read from cache michael@0: true, // hit server michael@0: true), // USE PRIVATE BROWSING, so not cached for later requests michael@0: new Test(httpBase + shortexpPath, 0, michael@0: true, // expect success michael@0: false, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + shortexpPath, 0, michael@0: true, // expect success michael@0: true, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + shortexpPath, Ci.nsIRequest.LOAD_BYPASS_CACHE, michael@0: true, // expect success michael@0: false, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + shortexpPath, Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE, michael@0: false, // expect success michael@0: false, // read from cache michael@0: false), // hit server michael@0: new Test(httpBase + shortexpPath, michael@0: Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | michael@0: Ci.nsIRequest.VALIDATE_NEVER, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: new Test(httpBase + shortexpPath, Ci.nsIRequest.LOAD_FROM_CACHE, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: michael@0: new Test(httpBase + longexpPath, 0, michael@0: true, // expect success michael@0: false, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + longexpPath, 0, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: new Test(httpBase + longexpPath, Ci.nsIRequest.LOAD_BYPASS_CACHE, michael@0: true, // expect success michael@0: false, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + longexpPath, michael@0: Ci.nsIRequest.VALIDATE_ALWAYS, michael@0: true, // expect success michael@0: true, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + longexpPath, Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: new Test(httpBase + longexpPath, michael@0: Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | michael@0: Ci.nsIRequest.VALIDATE_NEVER, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: new Test(httpBase + longexpPath, michael@0: Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | michael@0: Ci.nsIRequest.VALIDATE_ALWAYS, michael@0: false, // expect success michael@0: false, // read from cache michael@0: false), // hit server michael@0: new Test(httpBase + longexpPath, Ci.nsIRequest.LOAD_FROM_CACHE, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: michael@0: new Test(httpBase + longexp2Path, 0, michael@0: true, // expect success michael@0: false, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + longexp2Path, 0, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: michael@0: new Test(httpBase + nocachePath, 0, michael@0: true, // expect success michael@0: false, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + nocachePath, 0, michael@0: true, // expect success michael@0: true, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + nocachePath, Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE, michael@0: false, // expect success michael@0: false, // read from cache michael@0: false), // hit server michael@0: michael@0: // CACHE2: mayhemer - entry is doomed... I think the logic is wrong, we should not doom them michael@0: // as they are not valid, but take them as they need to reval michael@0: /* michael@0: new Test(httpBase + nocachePath, Ci.nsIRequest.LOAD_FROM_CACHE, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: */ michael@0: michael@0: // LOAD_ONLY_FROM_CACHE would normally fail (because no-cache forces michael@0: // a validation), but VALIDATE_NEVER should override that. michael@0: new Test(httpBase + nocachePath, michael@0: Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | michael@0: Ci.nsIRequest.VALIDATE_NEVER, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: michael@0: // ... however, no-cache over ssl should act like no-store and force michael@0: // a validation (and therefore failure) even if VALIDATE_NEVER is michael@0: // set. michael@0: /* XXX bug 466524: We can't currently start an ssl server in xpcshell tests, michael@0: so this test is currently disabled. michael@0: new Test(httpsBase + nocachePath, michael@0: Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | michael@0: Ci.nsIRequest.VALIDATE_NEVER, michael@0: false, // expect success michael@0: false, // read from cache michael@0: false) // hit server michael@0: */ michael@0: michael@0: new Test(httpBase + nostorePath, 0, michael@0: true, // expect success michael@0: false, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + nostorePath, 0, michael@0: true, // expect success michael@0: false, // read from cache michael@0: true), // hit server michael@0: new Test(httpBase + nostorePath, Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE, michael@0: false, // expect success michael@0: false, // read from cache michael@0: false), // hit server michael@0: new Test(httpBase + nostorePath, Ci.nsIRequest.LOAD_FROM_CACHE, michael@0: true, // expect success michael@0: true, // read from cache michael@0: false), // hit server michael@0: // no-store should force the validation (and therefore failure, with michael@0: // LOAD_ONLY_FROM_CACHE) even if VALIDATE_NEVER is set. michael@0: new Test(httpBase + nostorePath, michael@0: Ci.nsICachingChannel.LOAD_ONLY_FROM_CACHE | michael@0: Ci.nsIRequest.VALIDATE_NEVER, michael@0: false, // expect success michael@0: false, // read from cache michael@0: false) // hit server michael@0: ]; michael@0: michael@0: function run_next_test() michael@0: { michael@0: if (gTests.length == 0) { michael@0: httpserver.stop(do_test_finished); michael@0: return; michael@0: } michael@0: michael@0: var test = gTests.shift(); michael@0: test.run(); michael@0: } michael@0: michael@0: function handler(metadata, response) { michael@0: gHitServer = true; michael@0: try { michael@0: var etag = metadata.getHeader("If-None-Match"); michael@0: } catch(ex) { michael@0: var etag = ""; michael@0: } michael@0: if (etag == "testtag") { michael@0: // Allow using the cached data michael@0: response.setStatusLine(metadata.httpVersion, 304, "Not Modified"); michael@0: } else { michael@0: response.setStatusLine(metadata.httpVersion, 200, "OK"); michael@0: response.setHeader("Content-Type", "text/plain", false); michael@0: response.setHeader("ETag", "testtag", false); michael@0: const body = "data"; michael@0: response.bodyOutputStream.write(body, body.length); michael@0: } michael@0: } michael@0: michael@0: function nocache_handler(metadata, response) { michael@0: response.setHeader("Cache-Control", "no-cache", false); michael@0: handler(metadata, response); michael@0: } michael@0: michael@0: function nostore_handler(metadata, response) { michael@0: response.setHeader("Cache-Control", "no-store", false); michael@0: handler(metadata, response); michael@0: } michael@0: michael@0: function shortexp_handler(metadata, response) { michael@0: response.setHeader("Cache-Control", "max-age=0", false); michael@0: handler(metadata, response); michael@0: } michael@0: michael@0: function longexp_handler(metadata, response) { michael@0: response.setHeader("Cache-Control", "max-age=10000", false); michael@0: handler(metadata, response); michael@0: } michael@0: michael@0: // test spaces around max-age value token michael@0: function longexp2_handler(metadata, response) { michael@0: response.setHeader("Cache-Control", "max-age = 10000", false); michael@0: handler(metadata, response); michael@0: } michael@0: michael@0: function run_test() { michael@0: httpserver.registerPathHandler(shortexpPath, shortexp_handler); michael@0: httpserver.registerPathHandler(longexpPath, longexp_handler); michael@0: httpserver.registerPathHandler(longexp2Path, longexp2_handler); michael@0: httpserver.registerPathHandler(nocachePath, nocache_handler); michael@0: httpserver.registerPathHandler(nostorePath, nostore_handler); michael@0: michael@0: run_next_test(); michael@0: do_test_pending(); michael@0: }