netwerk/test/unit/head_channels.js

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /**
michael@0 2 * Read count bytes from stream and return as a String object
michael@0 3 */
michael@0 4 function read_stream(stream, count) {
michael@0 5 /* assume stream has non-ASCII data */
michael@0 6 var wrapper =
michael@0 7 Components.classes["@mozilla.org/binaryinputstream;1"]
michael@0 8 .createInstance(Components.interfaces.nsIBinaryInputStream);
michael@0 9 wrapper.setInputStream(stream);
michael@0 10 /* JS methods can be called with a maximum of 65535 arguments, and input
michael@0 11 streams don't have to return all the data they make .available() when
michael@0 12 asked to .read() that number of bytes. */
michael@0 13 var data = [];
michael@0 14 while (count > 0) {
michael@0 15 var bytes = wrapper.readByteArray(Math.min(65535, count));
michael@0 16 data.push(String.fromCharCode.apply(null, bytes));
michael@0 17 count -= bytes.length;
michael@0 18 if (bytes.length == 0)
michael@0 19 do_throw("Nothing read from input stream!");
michael@0 20 }
michael@0 21 return data.join('');
michael@0 22 }
michael@0 23
michael@0 24 const CL_EXPECT_FAILURE = 0x1;
michael@0 25 const CL_EXPECT_GZIP = 0x2;
michael@0 26 const CL_EXPECT_3S_DELAY = 0x4;
michael@0 27 const CL_SUSPEND = 0x8;
michael@0 28 const CL_ALLOW_UNKNOWN_CL = 0x10;
michael@0 29 const CL_EXPECT_LATE_FAILURE = 0x20;
michael@0 30 const CL_FROM_CACHE = 0x40; // Response must be from the cache
michael@0 31 const CL_NOT_FROM_CACHE = 0x80; // Response must NOT be from the cache
michael@0 32
michael@0 33 const SUSPEND_DELAY = 3000;
michael@0 34
michael@0 35 /**
michael@0 36 * A stream listener that calls a callback function with a specified
michael@0 37 * context and the received data when the channel is loaded.
michael@0 38 *
michael@0 39 * Signature of the closure:
michael@0 40 * void closure(in nsIRequest request, in ACString data, in JSObject context);
michael@0 41 *
michael@0 42 * This listener makes sure that various parts of the channel API are
michael@0 43 * implemented correctly and that the channel's status is a success code
michael@0 44 * (you can pass CL_EXPECT_FAILURE or CL_EXPECT_LATE_FAILURE as flags
michael@0 45 * to allow a failure code)
michael@0 46 *
michael@0 47 * Note that it also requires a valid content length on the channel and
michael@0 48 * is thus not fully generic.
michael@0 49 */
michael@0 50 function ChannelListener(closure, ctx, flags) {
michael@0 51 this._closure = closure;
michael@0 52 this._closurectx = ctx;
michael@0 53 this._flags = flags;
michael@0 54 }
michael@0 55 ChannelListener.prototype = {
michael@0 56 _closure: null,
michael@0 57 _closurectx: null,
michael@0 58 _buffer: "",
michael@0 59 _got_onstartrequest: false,
michael@0 60 _got_onstoprequest: false,
michael@0 61 _contentLen: -1,
michael@0 62 _lastEvent: 0,
michael@0 63
michael@0 64 QueryInterface: function(iid) {
michael@0 65 if (iid.equals(Components.interfaces.nsIStreamListener) ||
michael@0 66 iid.equals(Components.interfaces.nsIRequestObserver) ||
michael@0 67 iid.equals(Components.interfaces.nsISupports))
michael@0 68 return this;
michael@0 69 throw Components.results.NS_ERROR_NO_INTERFACE;
michael@0 70 },
michael@0 71
michael@0 72 onStartRequest: function(request, context) {
michael@0 73 try {
michael@0 74 if (this._got_onstartrequest)
michael@0 75 do_throw("Got second onStartRequest event!");
michael@0 76 this._got_onstartrequest = true;
michael@0 77 this._lastEvent = Date.now();
michael@0 78
michael@0 79 request.QueryInterface(Components.interfaces.nsIChannel);
michael@0 80 try {
michael@0 81 this._contentLen = request.contentLength;
michael@0 82 }
michael@0 83 catch (ex) {
michael@0 84 if (!(this._flags & (CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL)))
michael@0 85 do_throw("Could not get contentLength");
michael@0 86 }
michael@0 87 if (this._contentLen == -1 && !(this._flags & (CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL)))
michael@0 88 do_throw("Content length is unknown in onStartRequest!");
michael@0 89
michael@0 90 if ((this._flags & CL_FROM_CACHE)) {
michael@0 91 request.QueryInterface(Ci.nsICachingChannel);
michael@0 92 if (!request.isFromCache()) {
michael@0 93 do_throw("Response is not from the cache (CL_FROM_CACHE)");
michael@0 94 }
michael@0 95 }
michael@0 96 if ((this._flags & CL_NOT_FROM_CACHE)) {
michael@0 97 request.QueryInterface(Ci.nsICachingChannel);
michael@0 98 if (request.isFromCache()) {
michael@0 99 do_throw("Response is from the cache (CL_NOT_FROM_CACHE)");
michael@0 100 }
michael@0 101 }
michael@0 102
michael@0 103 if (this._flags & CL_SUSPEND) {
michael@0 104 request.suspend();
michael@0 105 do_timeout(SUSPEND_DELAY, function() { request.resume(); });
michael@0 106 }
michael@0 107
michael@0 108 } catch (ex) {
michael@0 109 do_throw("Error in onStartRequest: " + ex);
michael@0 110 }
michael@0 111 },
michael@0 112
michael@0 113 onDataAvailable: function(request, context, stream, offset, count) {
michael@0 114 try {
michael@0 115 let current = Date.now();
michael@0 116
michael@0 117 if (!this._got_onstartrequest)
michael@0 118 do_throw("onDataAvailable without onStartRequest event!");
michael@0 119 if (this._got_onstoprequest)
michael@0 120 do_throw("onDataAvailable after onStopRequest event!");
michael@0 121 if (!request.isPending())
michael@0 122 do_throw("request reports itself as not pending from onDataAvailable!");
michael@0 123 if (this._flags & CL_EXPECT_FAILURE)
michael@0 124 do_throw("Got data despite expecting a failure");
michael@0 125
michael@0 126 if (current - this._lastEvent >= SUSPEND_DELAY &&
michael@0 127 !(this._flags & CL_EXPECT_3S_DELAY))
michael@0 128 do_throw("Data received after significant unexpected delay");
michael@0 129 else if (current - this._lastEvent < SUSPEND_DELAY &&
michael@0 130 this._flags & CL_EXPECT_3S_DELAY)
michael@0 131 do_throw("Data received sooner than expected");
michael@0 132 else if (current - this._lastEvent >= SUSPEND_DELAY &&
michael@0 133 this._flags & CL_EXPECT_3S_DELAY)
michael@0 134 this._flags &= ~CL_EXPECT_3S_DELAY; // No more delays expected
michael@0 135
michael@0 136 this._buffer = this._buffer.concat(read_stream(stream, count));
michael@0 137 this._lastEvent = current;
michael@0 138 } catch (ex) {
michael@0 139 do_throw("Error in onDataAvailable: " + ex);
michael@0 140 }
michael@0 141 },
michael@0 142
michael@0 143 onStopRequest: function(request, context, status) {
michael@0 144 try {
michael@0 145 var success = Components.isSuccessCode(status);
michael@0 146 if (!this._got_onstartrequest)
michael@0 147 do_throw("onStopRequest without onStartRequest event!");
michael@0 148 if (this._got_onstoprequest)
michael@0 149 do_throw("Got second onStopRequest event!");
michael@0 150 this._got_onstoprequest = true;
michael@0 151 if ((this._flags & (CL_EXPECT_FAILURE | CL_EXPECT_LATE_FAILURE)) && success)
michael@0 152 do_throw("Should have failed to load URL (status is " + status.toString(16) + ")");
michael@0 153 else if (!(this._flags & (CL_EXPECT_FAILURE | CL_EXPECT_LATE_FAILURE)) && !success)
michael@0 154 do_throw("Failed to load URL: " + status.toString(16));
michael@0 155 if (status != request.status)
michael@0 156 do_throw("request.status does not match status arg to onStopRequest!");
michael@0 157 if (request.isPending())
michael@0 158 do_throw("request reports itself as pending from onStopRequest!");
michael@0 159 if (!(this._flags & (CL_EXPECT_FAILURE | CL_EXPECT_LATE_FAILURE)) &&
michael@0 160 !(this._flags & CL_EXPECT_GZIP) &&
michael@0 161 this._contentLen != -1)
michael@0 162 do_check_eq(this._buffer.length, this._contentLen)
michael@0 163 } catch (ex) {
michael@0 164 do_throw("Error in onStopRequest: " + ex);
michael@0 165 }
michael@0 166 try {
michael@0 167 this._closure(request, this._buffer, this._closurectx);
michael@0 168 } catch (ex) {
michael@0 169 do_throw("Error in closure function: " + ex);
michael@0 170 }
michael@0 171 }
michael@0 172 };
michael@0 173
michael@0 174 var ES_ABORT_REDIRECT = 0x01;
michael@0 175
michael@0 176 function ChannelEventSink(flags)
michael@0 177 {
michael@0 178 this._flags = flags;
michael@0 179 }
michael@0 180
michael@0 181 ChannelEventSink.prototype = {
michael@0 182 QueryInterface: function(iid) {
michael@0 183 if (iid.equals(Ci.nsIInterfaceRequestor) ||
michael@0 184 iid.equals(Ci.nsISupports))
michael@0 185 return this;
michael@0 186 throw Cr.NS_ERROR_NO_INTERFACE;
michael@0 187 },
michael@0 188
michael@0 189 getInterface: function(iid) {
michael@0 190 if (iid.equals(Ci.nsIChannelEventSink))
michael@0 191 return this;
michael@0 192 throw Cr.NS_ERROR_NO_INTERFACE;
michael@0 193 },
michael@0 194
michael@0 195 asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callback) {
michael@0 196 if (this._flags & ES_ABORT_REDIRECT)
michael@0 197 throw Cr.NS_BINDING_ABORTED;
michael@0 198
michael@0 199 callback.onRedirectVerifyCallback(Cr.NS_OK);
michael@0 200 }
michael@0 201 };
michael@0 202
michael@0 203
michael@0 204 /**
michael@0 205 * Class that implements nsILoadContext. Use it as callbacks for channel when
michael@0 206 * test needs it.
michael@0 207 */
michael@0 208 function LoadContextCallback(appId, inBrowserElement, isPrivate, isContent) {
michael@0 209 this.appId = appId;
michael@0 210 this.isInBrowserElement = inBrowserElement;
michael@0 211 this.usePrivateBrowsing = isPrivate;
michael@0 212 this.isContent = isContent;
michael@0 213 }
michael@0 214
michael@0 215 LoadContextCallback.prototype = {
michael@0 216 associatedWindow: null,
michael@0 217 topWindow : null,
michael@0 218 isAppOfType: function(appType) {
michael@0 219 throw Cr.NS_ERROR_NOT_IMPLEMENTED;
michael@0 220 },
michael@0 221 QueryInterface: function(iid) {
michael@0 222 if (iid.equals(Ci.nsILoadContext) ||
michael@0 223 iid.equals(Ci.nsIInterfaceRequestor) ||
michael@0 224 iid.equals(Ci.nsISupports)) {
michael@0 225 return this;
michael@0 226 }
michael@0 227 throw Cr.NS_ERROR_NO_INTERFACE;
michael@0 228 },
michael@0 229 getInterface: function(iid) {
michael@0 230 if (iid.equals(Ci.nsILoadContext))
michael@0 231 return this;
michael@0 232 throw Cr.NS_ERROR_NO_INTERFACE;
michael@0 233 },
michael@0 234 }
michael@0 235

mercurial