michael@0: // This file tests channel event sinks (bug 315598 et al) michael@0: michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: michael@0: XPCOMUtils.defineLazyGetter(this, "URL", function() { michael@0: return "http://localhost:" + httpserv.identity.primaryPort; michael@0: }); michael@0: michael@0: const sinkCID = Components.ID("{14aa4b81-e266-45cb-88f8-89595dece114}"); michael@0: const sinkContract = "@mozilla.org/network/unittest/channeleventsink;1"; michael@0: michael@0: const categoryName = "net-channel-event-sinks"; michael@0: michael@0: /** michael@0: * This object is both a factory and an nsIChannelEventSink implementation (so, it michael@0: * is de-facto a service). It's also an interface requestor that gives out michael@0: * itself when asked for nsIChannelEventSink. michael@0: */ michael@0: var eventsink = { michael@0: QueryInterface: function eventsink_qi(iid) { michael@0: if (iid.equals(Components.interfaces.nsISupports) || michael@0: iid.equals(Components.interfaces.nsIFactory) || michael@0: iid.equals(Components.interfaces.nsIChannelEventSink)) michael@0: return this; michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: createInstance: function eventsink_ci(outer, iid) { michael@0: if (outer) michael@0: throw Components.results.NS_ERROR_NO_AGGREGATION; michael@0: return this.QueryInterface(iid); michael@0: }, michael@0: lockFactory: function eventsink_lockf(lock) { michael@0: throw Components.results.NS_ERROR_NOT_IMPLEMENTED; michael@0: }, michael@0: michael@0: asyncOnChannelRedirect: function eventsink_onredir(oldChan, newChan, flags, callback) { michael@0: // veto michael@0: this.called = true; michael@0: throw Components.results.NS_BINDING_ABORTED; michael@0: }, michael@0: michael@0: getInterface: function eventsink_gi(iid) { michael@0: if (iid.equals(Components.interfaces.nsIChannelEventSink)) michael@0: return this; michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: michael@0: called: false michael@0: }; michael@0: michael@0: var listener = { michael@0: expectSinkCall: true, michael@0: michael@0: onStartRequest: function test_onStartR(request, ctx) { michael@0: try { michael@0: // Commenting out this check pending resolution of bug 255119 michael@0: //if (Components.isSuccessCode(request.status)) michael@0: // do_throw("Channel should have a failure code!"); michael@0: michael@0: // The current URI must be the original URI, as all redirects have been michael@0: // cancelled michael@0: if (!(request instanceof Components.interfaces.nsIChannel) || michael@0: !request.URI.equals(request.originalURI)) michael@0: do_throw("Wrong URI: Is <" + request.URI.spec + ">, should be <" + michael@0: request.originalURI.spec + ">"); michael@0: michael@0: if (request instanceof Components.interfaces.nsIHttpChannel) { michael@0: // As we expect a blocked redirect, verify that we have a 3xx status michael@0: do_check_eq(Math.floor(request.responseStatus / 100), 3); michael@0: do_check_eq(request.requestSucceeded, false); michael@0: } michael@0: michael@0: do_check_eq(eventsink.called, this.expectSinkCall); michael@0: } catch (e) { michael@0: do_throw("Unexpected exception: " + e); michael@0: } michael@0: michael@0: throw Components.results.NS_ERROR_ABORT; michael@0: }, michael@0: michael@0: onDataAvailable: function test_ODA() { michael@0: do_throw("Should not get any data!"); michael@0: }, michael@0: michael@0: onStopRequest: function test_onStopR(request, ctx, status) { michael@0: if (this._iteration <= 2) { michael@0: run_test_continued(); michael@0: } else { michael@0: do_test_pending(); michael@0: httpserv.stop(do_test_finished); michael@0: } michael@0: do_test_finished(); michael@0: }, michael@0: michael@0: _iteration: 1 michael@0: }; michael@0: michael@0: function makeChan(url) { michael@0: var ios = Components.classes["@mozilla.org/network/io-service;1"] michael@0: .getService(Components.interfaces.nsIIOService); michael@0: var chan = ios.newChannel(url, null, null) michael@0: .QueryInterface(Components.interfaces.nsIHttpChannel); michael@0: michael@0: return chan; michael@0: } michael@0: michael@0: var httpserv = null; michael@0: michael@0: function run_test() { michael@0: httpserv = new HttpServer(); michael@0: httpserv.registerPathHandler("/redirect", redirect); michael@0: httpserv.registerPathHandler("/redirectfile", redirectfile); michael@0: httpserv.start(-1); michael@0: michael@0: Components.manager.nsIComponentRegistrar.registerFactory(sinkCID, michael@0: "Unit test Event sink", sinkContract, eventsink); michael@0: michael@0: // Step 1: Set the callbacks on the listener itself michael@0: var chan = makeChan(URL + "/redirect"); michael@0: chan.notificationCallbacks = eventsink; michael@0: michael@0: chan.asyncOpen(listener, null); michael@0: michael@0: do_test_pending(); michael@0: } michael@0: michael@0: function run_test_continued() { michael@0: eventsink.called = false; michael@0: michael@0: var catMan = Components.classes["@mozilla.org/categorymanager;1"] michael@0: .getService(Components.interfaces.nsICategoryManager); michael@0: michael@0: var chan; michael@0: if (listener._iteration == 1) { michael@0: // Step 2: Category entry michael@0: catMan.nsICategoryManager.addCategoryEntry(categoryName, "unit test", michael@0: sinkContract, false, true); michael@0: chan = makeChan(URL + "/redirect") michael@0: } else { michael@0: // Step 3: Global contract id michael@0: catMan.nsICategoryManager.deleteCategoryEntry(categoryName, "unit test", michael@0: false); michael@0: listener.expectSinkCall = false; michael@0: chan = makeChan(URL + "/redirectfile"); michael@0: } michael@0: michael@0: listener._iteration++; michael@0: chan.asyncOpen(listener, null); michael@0: michael@0: do_test_pending(); michael@0: } michael@0: michael@0: // PATHS michael@0: michael@0: // /redirect michael@0: function redirect(metadata, response) { michael@0: response.setStatusLine(metadata.httpVersion, 301, "Moved Permanently"); michael@0: response.setHeader("Location", michael@0: "http://localhost:" + metadata.port + "/", michael@0: false); michael@0: michael@0: var body = "Moved\n"; michael@0: response.bodyOutputStream.write(body, body.length); michael@0: } michael@0: michael@0: // /redirectfile michael@0: function redirectfile(metadata, response) { michael@0: response.setStatusLine(metadata.httpVersion, 301, "Moved Permanently"); michael@0: response.setHeader("Content-Type", "text/plain", false); michael@0: response.setHeader("Location", "file:///etc/", false); michael@0: michael@0: var body = "Attempted to move to a file URI, but failed.\n"; michael@0: response.bodyOutputStream.write(body, body.length); michael@0: }