/* 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 test makes sure that the authorization header can get deleted e.g. by
// extensions if they are observing "http-on-modify-request". In a first step
// the auth cache is filled with credentials which then get added to the
// following request. On "http-on-modify-request" it is tested whether the
// authorization header got added at all and if so it gets removed. This test
// passes iff both succeeds.
"use strict";
const { HttpServer } = ChromeUtils.importESModule(
"resource://testing-common/httpd.sys.mjs"
);
var notification =
"http-on-modify-request";
var httpServer =
null;
var authCredentials =
"guest:guest";
var authPath =
"/authTest";
var authCredsURL =
"http://" + authCredentials + "@localhost:8888" + authPath;
var authURL =
"http://localhost:8888" + authPath;
function authHandler(metadata, response) {
if (metadata.hasHeader(
"Test")) {
// Lets see if the auth header got deleted.
var noAuthHeader =
false;
if (!metadata.hasHeader(
"Authorization")) {
noAuthHeader =
true;
}
Assert.ok(noAuthHeader);
}
// Not our test request yet.
else if (!metadata.hasHeader(
"Authorization")) {
response.setStatusLine(metadata.httpVersion, 401,
"Unauthorized");
response.setHeader(
"WWW-Authenticate",
'Basic realm="secret"',
false);
}
}
function RequestObserver() {
this.register();
}
RequestObserver.prototype = {
register() {
info(
"Registering " + notification);
Services.obs.addObserver(
this, notification,
true);
},
QueryInterface: ChromeUtils.generateQI([
"nsIObserver",
"nsISupportsWeakReference",
]),
observe(subject, topic) {
if (topic == notification) {
if (!(subject
instanceof Ci.nsIHttpChannel)) {
do_throw(notification +
" observed a non-HTTP channel.");
}
try {
subject.getRequestHeader(
"Authorization");
}
catch (e) {
// Throw if there is no header to delete. We should get one iff caching
// the auth credentials is working and the header gets added _before_
// "http-on-modify-request" gets called.
httpServer.stop(do_test_finished);
do_throw(
"No authorization header found, aborting!");
}
// We are still here. Let's remove the authorization header now.
subject.setRequestHeader(
"Authorization",
null,
false);
}
},
};
var listener = {
onStartRequest:
function test_onStartR() {},
onDataAvailable:
function test_ODA() {
do_throw(
"Should not get any data!");
},
onStopRequest:
function test_onStopR() {
if (current_test < tests.length - 1) {
current_test++;
tests[current_test]();
}
else {
do_test_pending();
httpServer.stop(do_test_finished);
}
do_test_finished();
},
};
function makeChan(url) {
return NetUtil.newChannel({
uri: url,
loadUsingSystemPrincipal:
true,
}).QueryInterface(Ci.nsIHttpChannel);
}
var tests = [startAuthHeaderTest, removeAuthHeaderTest];
var current_test = 0;
// Must create a RequestObserver for the test to pass, we keep it in memory
// to avoid garbage collection.
// eslint-disable-next-line no-unused-vars
var requestObserver =
null;
function run_test() {
httpServer =
new HttpServer();
httpServer.registerPathHandler(authPath, authHandler);
httpServer.start(8888);
tests[0]();
}
function startAuthHeaderTest() {
var chan = makeChan(authCredsURL);
chan.asyncOpen(listener);
do_test_pending();
}
function removeAuthHeaderTest() {
// After caching the auth credentials in the first test, lets try to remove
// the authorization header now...
requestObserver =
new RequestObserver();
var chan = makeChan(authURL);
// Indicating that the request is coming from the second test.
chan.setRequestHeader(
"Test",
"1",
false);
chan.asyncOpen(listener);
do_test_pending();
}