summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/test_suspend_channel_on_authRetry.js
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/test/unit/test_suspend_channel_on_authRetry.js')
-rw-r--r--netwerk/test/unit/test_suspend_channel_on_authRetry.js262
1 files changed, 262 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_suspend_channel_on_authRetry.js b/netwerk/test/unit/test_suspend_channel_on_authRetry.js
new file mode 100644
index 0000000000..3539b7a6fc
--- /dev/null
+++ b/netwerk/test/unit/test_suspend_channel_on_authRetry.js
@@ -0,0 +1,262 @@
+// This file tests async handling of a channel suspended in DoAuthRetry
+// notifying http-on-modify-request and http-on-before-connect observers.
+"use strict";
+
+const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
+
+XPCOMUtils.defineLazyGetter(this, "URL", function () {
+ return "http://localhost:" + httpserv.identity.primaryPort;
+});
+
+var obs = Services.obs;
+
+var requestObserver = null;
+
+function AuthPrompt() {}
+
+AuthPrompt.prototype = {
+ user: "guest",
+ pass: "guest",
+
+ QueryInterface: ChromeUtils.generateQI(["nsIAuthPrompt"]),
+
+ prompt: function ap1_prompt(title, text, realm, save, defaultText, result) {
+ do_throw("unexpected prompt call");
+ },
+
+ promptUsernameAndPassword: function promptUP(
+ title,
+ text,
+ realm,
+ savePW,
+ user,
+ pw
+ ) {
+ user.value = this.user;
+ pw.value = this.pass;
+
+ obs.addObserver(requestObserver, "http-on-before-connect");
+ obs.addObserver(requestObserver, "http-on-modify-request");
+ return true;
+ },
+
+ promptPassword: function promptPW(title, text, realm, save, pwd) {
+ do_throw("unexpected promptPassword call");
+ },
+};
+
+function requestListenerObserver(
+ suspendOnBeforeConnect,
+ suspendOnModifyRequest
+) {
+ this.suspendOnModifyRequest = suspendOnModifyRequest;
+ this.suspendOnBeforeConnect = suspendOnBeforeConnect;
+}
+
+requestListenerObserver.prototype = {
+ suspendOnModifyRequest: false,
+ suspendOnBeforeConnect: false,
+ gotOnBeforeConnect: false,
+ resumeOnBeforeConnect: false,
+ gotOnModifyRequest: false,
+ resumeOnModifyRequest: false,
+ QueryInterface: ChromeUtils.generateQI(["nsIObserver"]),
+
+ observe(subject, topic, data) {
+ if (
+ topic === "http-on-before-connect" &&
+ subject instanceof Ci.nsIHttpChannel
+ ) {
+ if (this.suspendOnBeforeConnect) {
+ let chan = subject.QueryInterface(Ci.nsIHttpChannel);
+ executeSoon(() => {
+ this.resumeOnBeforeConnect = true;
+ chan.resume();
+ });
+ this.gotOnBeforeConnect = true;
+ chan.suspend();
+ }
+ } else if (
+ topic === "http-on-modify-request" &&
+ subject instanceof Ci.nsIHttpChannel
+ ) {
+ if (this.suspendOnModifyRequest) {
+ let chan = subject.QueryInterface(Ci.nsIHttpChannel);
+ executeSoon(() => {
+ this.resumeOnModifyRequest = true;
+ chan.resume();
+ });
+ this.gotOnModifyRequest = true;
+ chan.suspend();
+ }
+ }
+ },
+};
+
+function Requestor() {}
+
+Requestor.prototype = {
+ QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor"]),
+
+ getInterface: function requestor_gi(iid) {
+ if (iid.equals(Ci.nsIAuthPrompt)) {
+ // Allow the prompt to store state by caching it here
+ if (!this.prompt) {
+ this.prompt = new AuthPrompt();
+ }
+ return this.prompt;
+ }
+
+ throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
+ },
+
+ prompt: null,
+};
+
+var listener = {
+ expectedCode: -1, // Uninitialized
+
+ onStartRequest: function test_onStartR(request) {
+ try {
+ if (!Components.isSuccessCode(request.status)) {
+ do_throw("Channel should have a success code!");
+ }
+
+ if (!(request instanceof Ci.nsIHttpChannel)) {
+ do_throw("Expecting an HTTP channel");
+ }
+
+ Assert.equal(request.responseStatus, this.expectedCode);
+ // The request should be succeeded iff we expect 200
+ Assert.equal(request.requestSucceeded, this.expectedCode == 200);
+ } catch (e) {
+ do_throw("Unexpected exception: " + e);
+ }
+ throw Components.Exception("", Cr.NS_ERROR_ABORT);
+ },
+
+ onDataAvailable: function test_ODA() {
+ do_throw("Should not get any data!");
+ },
+
+ onStopRequest: function test_onStopR(request, status) {
+ Assert.equal(status, Cr.NS_ERROR_ABORT);
+ if (requestObserver.suspendOnBeforeConnect) {
+ Assert.ok(
+ requestObserver.gotOnBeforeConnect &&
+ requestObserver.resumeOnBeforeConnect
+ );
+ }
+ if (requestObserver.suspendOnModifyRequest) {
+ Assert.ok(
+ requestObserver.gotOnModifyRequest &&
+ requestObserver.resumeOnModifyRequest
+ );
+ }
+ obs.removeObserver(requestObserver, "http-on-before-connect");
+ obs.removeObserver(requestObserver, "http-on-modify-request");
+ moveToNextTest();
+ },
+};
+
+function makeChan(url, loadingUrl) {
+ var principal = Services.scriptSecurityManager.createContentPrincipal(
+ Services.io.newURI(loadingUrl),
+ {}
+ );
+ return NetUtil.newChannel({
+ uri: url,
+ loadingPrincipal: principal,
+ securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
+ contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
+ });
+}
+
+var tests = [
+ test_suspend_on_before_connect,
+ test_suspend_on_modify_request,
+ test_suspend_all,
+];
+
+var current_test = 0;
+
+var httpserv = null;
+
+function moveToNextTest() {
+ if (current_test < tests.length - 1) {
+ // First, gotta clear the auth cache
+ Cc["@mozilla.org/network/http-auth-manager;1"]
+ .getService(Ci.nsIHttpAuthManager)
+ .clearAll();
+
+ current_test++;
+ tests[current_test]();
+ } else {
+ do_test_pending();
+ httpserv.stop(do_test_finished);
+ }
+
+ do_test_finished();
+}
+
+function run_test() {
+ httpserv = new HttpServer();
+
+ httpserv.registerPathHandler("/auth", authHandler);
+
+ httpserv.start(-1);
+
+ tests[0]();
+}
+
+function test_suspend_on_auth(suspendOnBeforeConnect, suspendOnModifyRequest) {
+ var chan = makeChan(URL + "/auth", URL);
+ requestObserver = new requestListenerObserver(
+ suspendOnBeforeConnect,
+ suspendOnModifyRequest
+ );
+ chan.notificationCallbacks = new Requestor();
+ listener.expectedCode = 200; // OK
+ chan.asyncOpen(listener);
+
+ do_test_pending();
+}
+
+function test_suspend_on_before_connect() {
+ test_suspend_on_auth(true, false);
+}
+
+function test_suspend_on_modify_request() {
+ test_suspend_on_auth(false, true);
+}
+
+function test_suspend_all() {
+ test_suspend_on_auth(true, true);
+}
+
+// PATH HANDLERS
+
+// /auth
+function authHandler(metadata, response) {
+ // btoa("guest:guest"), but that function is not available here
+ var expectedHeader = "Basic Z3Vlc3Q6Z3Vlc3Q=";
+
+ var body;
+ if (
+ metadata.hasHeader("Authorization") &&
+ metadata.getHeader("Authorization") == expectedHeader
+ ) {
+ response.setStatusLine(metadata.httpVersion, 200, "OK, authorized");
+ response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
+
+ body = "success";
+ } else {
+ // didn't know guest:guest, failure
+ response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
+ response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
+
+ body = "failed";
+ }
+
+ response.bodyOutputStream.write(body, body.length);
+}