extensions/cookie/test/channel_utils.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial