Bug 591102 - Ensure exceptions from [Async]Resource contain the status code. r=mconnor

This commit is contained in:
Philipp von Weitershausen 2011-01-31 20:55:48 -08:00
parent 29368145cf
commit 2985d253e2
3 changed files with 52 additions and 16 deletions

View File

@ -142,6 +142,9 @@ function AsyncResource(uri) {
AsyncResource.prototype = {
_logName: "Net.Resource",
// Wait 5 minutes before killing a request
ABORT_TIMEOUT: 300000,
// ** {{{ Resource.authenticator }}} **
//
// Getter and setter for the authenticator module
@ -270,7 +273,7 @@ AsyncResource.prototype = {
// Setup a channel listener so that the actual network operation
// is performed asynchronously.
let listener = new ChannelListener(this._onComplete, this._onProgress,
this._log);
this._log, this.ABORT_TIMEOUT);
channel.requestMethod = action;
channel.asyncOpen(listener, null);
},
@ -411,8 +414,10 @@ Resource.prototype = {
try {
return doRequest(action, data, callback);
} catch(ex) {
// Combine the channel stack with this request stack
// Combine the channel stack with this request stack. Need to create
// a new error object for that.
let error = Error(ex.message);
error.result = ex.result;
let chanStack = [];
if (ex.stack)
chanStack = ex.stack.trim().split(/\n/).slice(1);
@ -466,15 +471,14 @@ Resource.prototype = {
//
// This object implements the {{{nsIStreamListener}}} interface
// and is called as the network operation proceeds.
function ChannelListener(onComplete, onProgress, logger) {
function ChannelListener(onComplete, onProgress, logger, timeout) {
this._onComplete = onComplete;
this._onProgress = onProgress;
this._log = logger;
this._timeout = timeout;
this.delayAbort();
}
ChannelListener.prototype = {
// Wait 5 minutes before killing a request
ABORT_TIMEOUT: 300000,
onStartRequest: function Channel_onStartRequest(channel) {
channel.QueryInterface(Ci.nsIHttpChannel);
@ -497,9 +501,13 @@ ChannelListener.prototype = {
if (this._data == '')
this._data = null;
// Throw the failure code name (and stop execution)
// Throw the failure code and stop execution. Use Components.Exception()
// instead of Error() so the exception is QI-able and can be passed across
// XPCOM borders while preserving the status code.
if (!Components.isSuccessCode(status)) {
this._onComplete(Error(Components.Exception("", status).name));
let message = Components.Exception("", status).name;
let error = Components.Exception(message, status);
this._onComplete(error);
return;
}
@ -535,14 +543,15 @@ ChannelListener.prototype = {
* Create or push back the abort timer that kills this request
*/
delayAbort: function delayAbort() {
Utils.delay(this.abortRequest, this.ABORT_TIMEOUT, this, "abortTimer");
Utils.delay(this.abortRequest, this._timeout, this, "abortTimer");
},
abortRequest: function abortRequest() {
// Ignore any callbacks if we happen to get any now
this.onStopRequest = function() {};
this.onDataAvailable = function() {};
this._onComplete(Error("Aborting due to channel inactivity."));
let error = Components.Exception("Aborting due to channel inactivity.",
Cr.NS_ERROR_NET_TIMEOUT);
this._onComplete(error);
}
};

View File

@ -3,6 +3,7 @@ Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/log4moz.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/ext/Sync.js");
let logger;
@ -189,7 +190,7 @@ function run_test() {
Utils.prefs.setIntPref("network.numRetries", 1); // speed up test
_("Resource object memebers");
_("Resource object members");
let res = new Resource("http://localhost:8080/open");
do_check_true(res.uri instanceof Ci.nsIURI);
do_check_eq(res.uri.spec, "http://localhost:8080/open");
@ -406,6 +407,7 @@ function run_test() {
} catch(ex) {
error = ex;
}
do_check_eq(error.result, Cr.NS_ERROR_CONNECTION_REFUSED);
do_check_eq(error.message, "NS_ERROR_CONNECTION_REFUSED");
do_check_eq(typeof error.stack, "string");
@ -489,6 +491,7 @@ function run_test() {
}
// It throws and logs.
do_check_eq(error.result, Cr.NS_ERROR_MALFORMED_URI);
do_check_eq(error, "Error: NS_ERROR_MALFORMED_URI");
do_check_eq(warnings.pop(),
"Got exception calling onProgress handler during fetch of " +
@ -511,11 +514,23 @@ function run_test() {
}
// It throws and logs.
do_check_eq(error.result, Cr.NS_ERROR_XPC_JS_THREW_STRING);
do_check_eq(error, "Error: NS_ERROR_XPC_JS_THREW_STRING");
do_check_eq(warnings.pop(),
"Got exception calling onProgress handler during fetch of " +
"http://localhost:8080/json");
_("Ensure channel timeouts are thrown appropriately.");
let res19 = new Resource("http://localhost:8080/json");
res19.ABORT_TIMEOUT = 0;
error = undefined;
try {
content = res19.get();
} catch (ex) {
error = ex;
}
do_check_eq(error.result, Cr.NS_ERROR_NET_TIMEOUT);
server.stop(do_test_finished);
}

View File

@ -556,8 +556,8 @@ function run_test() {
let res11 = new AsyncResource("http://localhost:12345/does/not/exist");
res11.get(ensureThrows(function (error, content) {
do_check_neq(error, null);
do_check_eq(error.result, Cr.NS_ERROR_CONNECTION_REFUSED);
do_check_eq(error.message, "NS_ERROR_CONNECTION_REFUSED");
do_check_eq(typeof error.stack, "string");
do_test_finished();
next();
}));
@ -621,7 +621,8 @@ function run_test() {
res14._log.warn = function(msg) { warnings.push(msg) };
res14.get(ensureThrows(function (error, content) {
do_check_eq(error, "Error: NS_ERROR_MALFORMED_URI");
do_check_eq(error.result, Cr.NS_ERROR_MALFORMED_URI);
do_check_eq(error.message, "NS_ERROR_MALFORMED_URI");
do_check_eq(content, null);
do_check_eq(warnings.pop(),
"Got exception calling onProgress handler during fetch of " +
@ -643,7 +644,8 @@ function run_test() {
res15._log.warn = function(msg) { warnings.push(msg) };
res15.get(ensureThrows(function (error, content) {
do_check_eq(error, "Error: NS_ERROR_XPC_JS_THREW_STRING");
do_check_eq(error.result, Cr.NS_ERROR_XPC_JS_THREW_STRING);
do_check_eq(error.message, "NS_ERROR_XPC_JS_THREW_STRING");
do_check_eq(content, null);
do_check_eq(warnings.pop(),
"Got exception calling onProgress handler during fetch of " +
@ -653,6 +655,16 @@ function run_test() {
next();
}));
}, function (next) {
_("Ensure channel timeouts are thrown appropriately.");
let res19 = new AsyncResource("http://localhost:8080/json");
res19.ABORT_TIMEOUT = 0;
res19.get(ensureThrows(function (error, content) {
do_check_eq(error.result, Cr.NS_ERROR_NET_TIMEOUT);
next();
}));
}, function (next) {
// Don't quit test harness before server shuts down.