gecko/netwerk/test/unit/test_auth_proxy.js
Jim Blandy 4d6a633bba Bug 914753: Make Emacs file variable header lines correct, or at least consistent. DONTBUILD r=ehsan
The -*- file variable lines -*- establish per-file settings that Emacs will
pick up. This patch makes the following changes to those lines (and touches
nothing else):

 - Never set the buffer's mode.

   Years ago, Emacs did not have a good JavaScript mode, so it made sense
   to use Java or C++ mode in .js files. However, Emacs has had js-mode for
   years now; it's perfectly serviceable, and is available and enabled by
   default in all major Emacs packagings.

   Selecting a mode in the -*- file variable line -*- is almost always the
   wrong thing to do anyway. It overrides Emacs's default choice, which is
   (now) reasonable; and even worse, it overrides settings the user might
   have made in their '.emacs' file for that file extension. It's only
   useful when there's something specific about that particular file that
   makes a particular mode appropriate.

 - Correctly propagate settings that establish the correct indentation
   level for this file: c-basic-offset and js2-basic-offset should be
   js-indent-level. Whatever value they're given should be preserved;
   different parts of our tree use different indentation styles.

 - We don't use tabs in Mozilla JS code. Always set indent-tabs-mode: nil.
   Remove tab-width: settings, at least in files that don't contain tab
   characters.

 - Remove js2-mode settings that belong in the user's .emacs file, like
   js2-skip-preprocessor-directives.
2014-06-24 22:12:07 -07:00

370 lines
11 KiB
JavaScript

/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* This tests the automatic login to the proxy with password,
* if the password is stored and the browser is restarted.
*
* <copied from="test_authentication.js"/>
*/
Cu.import("resource://testing-common/httpd.js");
const FLAG_RETURN_FALSE = 1 << 0;
const FLAG_WRONG_PASSWORD = 1 << 1;
const FLAG_PREVIOUS_FAILED = 1 << 2;
function AuthPrompt2(proxyFlags, hostFlags) {
this.proxyCred.flags = proxyFlags;
this.hostCred.flags = hostFlags;
}
AuthPrompt2.prototype = {
proxyCred : { user: "proxy", pass: "guest",
realmExpected: "intern", flags : 0 },
hostCred : { user: "host", pass: "guest",
realmExpected: "extern", flags : 0 },
QueryInterface: function authprompt2_qi(iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIAuthPrompt2))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
promptAuth:
function ap2_promptAuth(channel, encryptionLevel, authInfo)
{
try {
// never HOST and PROXY set at the same time in prompt
do_check_eq((authInfo.flags & Ci.nsIAuthInformation.AUTH_HOST) != 0,
(authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) == 0);
var isProxy = (authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) != 0;
var cred = isProxy ? this.proxyCred : this.hostCred;
dump("with flags: " +
((cred.flags & FLAG_WRONG_PASSWORD) !=0 ? "wrong password" : "")+" "+
((cred.flags & FLAG_PREVIOUS_FAILED) !=0 ? "previous failed" : "")+" "+
((cred.flags & FLAG_RETURN_FALSE) !=0 ? "return false" : "") + "\n");
// PROXY properly set by necko (checked using realm)
do_check_eq(cred.realmExpected, authInfo.realm);
// PREVIOUS_FAILED properly set by necko
do_check_eq((cred.flags & FLAG_PREVIOUS_FAILED) != 0,
(authInfo.flags & Ci.nsIAuthInformation.PREVIOUS_FAILED) != 0);
if (cred.flags & FLAG_RETURN_FALSE)
{
cred.flags |= FLAG_PREVIOUS_FAILED;
cred.flags &= ~FLAG_RETURN_FALSE;
return false;
}
authInfo.username = cred.user;
if (cred.flags & FLAG_WRONG_PASSWORD) {
authInfo.password = cred.pass + ".wrong";
cred.flags |= FLAG_PREVIOUS_FAILED;
// Now clear the flag to avoid an infinite loop
cred.flags &= ~FLAG_WRONG_PASSWORD;
} else {
authInfo.password = cred.pass;
cred.flags &= ~FLAG_PREVIOUS_FAILED;
}
return true;
} catch (e) { do_throw(e); }
},
asyncPromptAuth:
function ap2_async(channel, callback, context, encryptionLevel, authInfo)
{
try {
var me = this;
var allOverAndDead = false;
do_execute_soon(function() {
try {
if (allOverAndDead)
throw "already canceled";
var ret = me.promptAuth(channel, encryptionLevel, authInfo);
if (!ret)
callback.onAuthCancelled(context, true);
else
callback.onAuthAvailable(context, authInfo);
allOverAndDead = true;
} catch (e) { do_throw(e); }
});
return new Cancelable(function() {
if (allOverAndDead)
throw "can't cancel, already ran";
callback.onAuthAvailable(context, authInfo);
allOverAndDead = true;
});
} catch (e) { do_throw(e); }
}
};
function Cancelable(onCancelFunc) {
this.onCancelFunc = onCancelFunc;
}
Cancelable.prototype = {
QueryInterface: function cancelable_qi(iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsICancelable))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
cancel: function cancel() {
try {
this.onCancelFunc();
} catch (e) { do_throw(e); }
}
};
function Requestor(proxyFlags, hostFlags) {
this.proxyFlags = proxyFlags;
this.hostFlags = hostFlags;
}
Requestor.prototype = {
QueryInterface: function requestor_qi(iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIInterfaceRequestor))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
getInterface: function requestor_gi(iid) {
if (iid.equals(Ci.nsIAuthPrompt)) {
dump("authprompt1 not implemented\n");
throw Cr.NS_ERROR_NO_INTERFACE;
}
if (iid.equals(Ci.nsIAuthPrompt2)) {
try {
// Allow the prompt to store state by caching it here
if (!this.prompt2)
this.prompt2 = new AuthPrompt2(this.proxyFlags, this.hostFlags);
return this.prompt2;
} catch (e) { do_throw(e); }
}
throw Cr.NS_ERROR_NO_INTERFACE;
},
prompt2: null
};
var listener = {
expectedCode: -1, // uninitialized
onStartRequest: function test_onStartR(request, ctx) {
try {
// Proxy auth cancellation return failures to avoid spoofing
if (!Components.isSuccessCode(request.status) &&
(this.expectedCode != 407))
do_throw("Channel should have a success code!");
if (!(request instanceof Ci.nsIHttpChannel))
do_throw("Expecting an HTTP channel");
do_check_eq(this.expectedCode, request.responseStatus);
// If we expect 200, the request should have succeeded
do_check_eq(this.expectedCode == 200, request.requestSucceeded);
} catch (e) {
do_throw("Unexpected exception: " + e);
}
throw Cr.NS_ERROR_ABORT;
},
onDataAvailable: function test_ODA() {
do_throw("Should not get any data!");
},
onStopRequest: function test_onStopR(request, ctx, status) {
do_check_eq(status, Cr.NS_ERROR_ABORT);
if (current_test < (tests.length - 1)) {
// First, need to 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 makeChan(url) {
if (!url)
url = "http://somesite/";
var ios = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var chan = ios.newChannel(url, null, null)
.QueryInterface(Ci.nsIHttpChannel);
return chan;
}
var current_test = 0;
var httpserv = null;
function run_test() {
httpserv = new HttpServer();
httpserv.registerPathHandler("/", proxyAuthHandler);
httpserv.identity.add("http", "somesite", 80);
httpserv.start(-1);
const prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
prefs.setCharPref("network.proxy.http", "localhost");
prefs.setIntPref("network.proxy.http_port", httpserv.identity.primaryPort);
prefs.setCharPref("network.proxy.no_proxies_on", "");
prefs.setIntPref("network.proxy.type", 1);
tests[current_test]();
}
function test_proxy_returnfalse() {
dump("\ntest: proxy returnfalse\n");
var chan = makeChan();
chan.notificationCallbacks = new Requestor(FLAG_RETURN_FALSE, 0);
listener.expectedCode = 407; // Proxy Unauthorized
chan.asyncOpen(listener, null);
do_test_pending();
}
function test_proxy_wrongpw() {
dump("\ntest: proxy wrongpw\n");
var chan = makeChan();
chan.notificationCallbacks = new Requestor(FLAG_WRONG_PASSWORD, 0);
listener.expectedCode = 200; // Eventually OK
chan.asyncOpen(listener, null);
do_test_pending();
}
function test_all_ok() {
dump("\ntest: all ok\n");
var chan = makeChan();
chan.notificationCallbacks = new Requestor(0, 0);
listener.expectedCode = 200; // OK
chan.asyncOpen(listener, null);
do_test_pending();
}
function test_host_returnfalse() {
dump("\ntest: host returnfalse\n");
var chan = makeChan();
chan.notificationCallbacks = new Requestor(0, FLAG_RETURN_FALSE);
listener.expectedCode = 401; // Host Unauthorized
chan.asyncOpen(listener, null);
do_test_pending();
}
function test_host_wrongpw() {
dump("\ntest: host wrongpw\n");
var chan = makeChan();
chan.notificationCallbacks = new Requestor(0, FLAG_WRONG_PASSWORD);
listener.expectedCode = 200; // Eventually OK
chan.asyncOpen(listener, null);
do_test_pending();
}
function test_proxy_wrongpw_host_wrongpw() {
dump("\ntest: proxy wrongpw, host wrongpw\n");
var chan = makeChan();
chan.notificationCallbacks =
new Requestor(FLAG_WRONG_PASSWORD, FLAG_WRONG_PASSWORD);
listener.expectedCode = 200; // OK
chan.asyncOpen(listener, null);
do_test_pending();
}
function test_proxy_wrongpw_host_returnfalse() {
dump("\ntest: proxy wrongpw, host return false\n");
var chan = makeChan();
chan.notificationCallbacks =
new Requestor(FLAG_WRONG_PASSWORD, FLAG_RETURN_FALSE);
listener.expectedCode = 401; // Host Unauthorized
chan.asyncOpen(listener, null);
do_test_pending();
}
var tests = [test_proxy_returnfalse, test_proxy_wrongpw, test_all_ok,
test_host_returnfalse, test_host_wrongpw,
test_proxy_wrongpw_host_wrongpw, test_proxy_wrongpw_host_returnfalse];
// PATH HANDLERS
// Proxy
function proxyAuthHandler(metadata, response) {
try {
var realm = "intern";
// btoa("proxy:guest"), but that function is not available here
var expectedHeader = "Basic cHJveHk6Z3Vlc3Q=";
var body;
if (metadata.hasHeader("Proxy-Authorization") &&
metadata.getHeader("Proxy-Authorization") == expectedHeader)
{
dump("proxy password ok\n");
response.setHeader("Proxy-Authenticate",
'Basic realm="' + realm + '"', false);
hostAuthHandler(metadata, response);
}
else
{
dump("proxy password required\n");
response.setStatusLine(metadata.httpVersion, 407,
"Unauthorized by HTTP proxy");
response.setHeader("Proxy-Authenticate",
'Basic realm="' + realm + '"', false);
body = "failed";
response.bodyOutputStream.write(body, body.length);
}
} catch (e) { do_throw(e); }
}
// Host /auth
function hostAuthHandler(metadata, response) {
try {
var realm = "extern";
// btoa("host:guest"), but that function is not available here
var expectedHeader = "Basic aG9zdDpndWVzdA==";
var body;
if (metadata.hasHeader("Authorization") &&
metadata.getHeader("Authorization") == expectedHeader)
{
dump("host password ok\n");
response.setStatusLine(metadata.httpVersion, 200,
"OK, authorized for host");
response.setHeader("WWW-Authenticate",
'Basic realm="' + realm + '"', false);
body = "success";
}
else
{
dump("host password required\n");
response.setStatusLine(metadata.httpVersion, 401,
"Unauthorized by HTTP server host");
response.setHeader("WWW-Authenticate",
'Basic realm="' + realm + '"', false);
body = "failed";
}
response.bodyOutputStream.write(body, body.length);
} catch (e) { do_throw(e); }
}