test_event_sink.js (4645B)
1 // This file tests channel event sinks (bug 315598 et al) 2 3 "use strict"; 4 5 const { HttpServer } = ChromeUtils.importESModule( 6 "resource://testing-common/httpd.sys.mjs" 7 ); 8 9 ChromeUtils.defineLazyGetter(this, "URL", function () { 10 return "http://localhost:" + httpserv.identity.primaryPort; 11 }); 12 13 const sinkCID = Components.ID("{14aa4b81-e266-45cb-88f8-89595dece114}"); 14 const sinkContract = "@mozilla.org/network/unittest/channeleventsink;1"; 15 16 const categoryName = "net-channel-event-sinks"; 17 18 /** 19 * This object is both a factory and an nsIChannelEventSink implementation (so, it 20 * is de-facto a service). It's also an interface requestor that gives out 21 * itself when asked for nsIChannelEventSink. 22 */ 23 var eventsink = { 24 QueryInterface: ChromeUtils.generateQI(["nsIFactory", "nsIChannelEventSink"]), 25 createInstance: function eventsink_ci(iid) { 26 return this.QueryInterface(iid); 27 }, 28 29 asyncOnChannelRedirect: function eventsink_onredir() { 30 // veto 31 this.called = true; 32 throw Components.Exception("", Cr.NS_BINDING_ABORTED); 33 }, 34 35 getInterface: function eventsink_gi(iid) { 36 if (iid.equals(Ci.nsIChannelEventSink)) { 37 return this; 38 } 39 throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE); 40 }, 41 42 called: false, 43 }; 44 45 var listener = { 46 expectSinkCall: true, 47 48 onStartRequest: function test_onStartR(request) { 49 try { 50 // Commenting out this check pending resolution of bug 255119 51 //if (Components.isSuccessCode(request.status)) 52 // do_throw("Channel should have a failure code!"); 53 54 // The current URI must be the original URI, as all redirects have been 55 // cancelled 56 if ( 57 !(request instanceof Ci.nsIChannel) || 58 !request.URI.equals(request.originalURI) 59 ) { 60 do_throw( 61 "Wrong URI: Is <" + 62 request.URI.spec + 63 ">, should be <" + 64 request.originalURI.spec + 65 ">" 66 ); 67 } 68 69 if (request instanceof Ci.nsIHttpChannel) { 70 // As we expect a blocked redirect, verify that we have a 3xx status 71 Assert.equal(Math.floor(request.responseStatus / 100), 3); 72 Assert.equal(request.requestSucceeded, false); 73 } 74 75 Assert.equal(eventsink.called, this.expectSinkCall); 76 } catch (e) { 77 do_throw("Unexpected exception: " + e); 78 } 79 80 throw Components.Exception("", Cr.NS_ERROR_ABORT); 81 }, 82 83 onDataAvailable: function test_ODA() { 84 do_throw("Should not get any data!"); 85 }, 86 87 onStopRequest: function test_onStopR() { 88 if (this._iteration <= 2) { 89 run_test_continued(); 90 } else { 91 do_test_pending(); 92 httpserv.stop(do_test_finished); 93 } 94 do_test_finished(); 95 }, 96 97 _iteration: 1, 98 }; 99 100 function makeChan(url) { 101 return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true }); 102 } 103 104 var httpserv = null; 105 106 function run_test() { 107 httpserv = new HttpServer(); 108 httpserv.registerPathHandler("/redirect", redirect); 109 httpserv.registerPathHandler("/redirectfile", redirectfile); 110 httpserv.start(-1); 111 112 Components.manager.nsIComponentRegistrar.registerFactory( 113 sinkCID, 114 "Unit test Event sink", 115 sinkContract, 116 eventsink 117 ); 118 119 // Step 1: Set the callbacks on the listener itself 120 var chan = makeChan(URL + "/redirect"); 121 chan.notificationCallbacks = eventsink; 122 123 chan.asyncOpen(listener); 124 125 do_test_pending(); 126 } 127 128 function run_test_continued() { 129 eventsink.called = false; 130 131 var chan; 132 if (listener._iteration == 1) { 133 // Step 2: Category entry 134 Services.catMan.addCategoryEntry( 135 categoryName, 136 "unit test", 137 sinkContract, 138 false, 139 true 140 ); 141 chan = makeChan(URL + "/redirect"); 142 } else { 143 // Step 3: Global contract id 144 Services.catMan.deleteCategoryEntry(categoryName, "unit test", false); 145 listener.expectSinkCall = false; 146 chan = makeChan(URL + "/redirectfile"); 147 } 148 149 listener._iteration++; 150 chan.asyncOpen(listener); 151 152 do_test_pending(); 153 } 154 155 // PATHS 156 157 // /redirect 158 function redirect(metadata, response) { 159 response.setStatusLine(metadata.httpVersion, 301, "Moved Permanently"); 160 response.setHeader( 161 "Location", 162 "http://localhost:" + metadata.port + "/", 163 false 164 ); 165 166 var body = "Moved\n"; 167 response.bodyOutputStream.write(body, body.length); 168 } 169 170 // /redirectfile 171 function redirectfile(metadata, response) { 172 response.setStatusLine(metadata.httpVersion, 301, "Moved Permanently"); 173 response.setHeader("Content-Type", "text/plain", false); 174 response.setHeader("Location", "file:///etc/", false); 175 176 var body = "Attempted to move to a file URI, but failed.\n"; 177 response.bodyOutputStream.write(body, body.length); 178 }