"use strict"; XPCOMUtils.defineLazyServiceGetter( this, "authManager", "@mozilla.org/network/http-auth-manager;1", "nsIHttpAuthManager" ); const proxy = createHttpServer(); // accept proxy connections for mozilla.org proxy.identity.add("http", "mozilla.org", 80); proxy.identity.add("https", "407.example.com", 443); proxy.registerPathHandler("CONNECT", (request, response) => { Assert.equal(request.method, "CONNECT"); switch (request.host) { case "407.example.com": response.setStatusLine(request.httpVersion, 407, "Authenticate"); response.setHeader("Content-Type", "text/plain", false); response.setHeader("Proxy-Authenticate", 'Basic realm="foobar"', false); response.write("auth required"); break; default: response.setStatusLine(request.httpVersion, 500, "I am dumb"); } }); proxy.registerPathHandler("/", (request, response) => { if (request.hasHeader("Proxy-Authorization")) { response.setStatusLine(request.httpVersion, 200, "OK"); response.setHeader("Content-Type", "text/plain", false); response.write("ok, got proxy auth"); } else { response.setStatusLine( request.httpVersion, 407, "Proxy authentication required" ); response.setHeader("Content-Type", "text/plain", false); response.setHeader("Proxy-Authenticate", 'Basic realm="foobar"', false); response.write("auth required"); } }); function getExtension(background) { return ExtensionTestUtils.loadExtension({ manifest: { permissions: ["proxy", "webRequest", "webRequestBlocking", ""], }, background: `(${background})(${proxy.identity.primaryPort})`, }); } add_task(async function test_webRequest_auth_proxy() { async function background(port) { let expecting = [ "onBeforeSendHeaders", "onSendHeaders", "onAuthRequired", "onBeforeSendHeaders", "onSendHeaders", "onCompleted", ]; browser.webRequest.onBeforeSendHeaders.addListener( details => { browser.test.log(`onBeforeSendHeaders ${JSON.stringify(details)}\n`); browser.test.assertEq( "onBeforeSendHeaders", expecting.shift(), "got expected event" ); browser.test.assertEq( "localhost", details.proxyInfo.host, "proxy host" ); browser.test.assertEq(port, details.proxyInfo.port, "proxy port"); browser.test.assertEq("http", details.proxyInfo.type, "proxy type"); browser.test.assertEq( "", details.proxyInfo.username, "proxy username not set" ); }, { urls: [""] } ); browser.webRequest.onSendHeaders.addListener( details => { browser.test.log(`onSendHeaders ${JSON.stringify(details)}\n`); browser.test.assertEq( "onSendHeaders", expecting.shift(), "got expected event" ); }, { urls: [""] } ); browser.webRequest.onAuthRequired.addListener( details => { browser.test.log(`onAuthRequired ${JSON.stringify(details)}\n`); browser.test.assertEq( "onAuthRequired", expecting.shift(), "got expected event" ); browser.test.assertTrue(details.isProxy, "proxied request"); browser.test.assertEq( "localhost", details.proxyInfo.host, "proxy host" ); browser.test.assertEq(port, details.proxyInfo.port, "proxy port"); browser.test.assertEq("http", details.proxyInfo.type, "proxy type"); browser.test.assertEq( "localhost", details.challenger.host, "proxy host" ); browser.test.assertEq(port, details.challenger.port, "proxy port"); return { authCredentials: { username: "puser", password: "ppass" } }; }, { urls: [""] }, ["blocking"] ); browser.webRequest.onCompleted.addListener( details => { browser.test.log(`onCompleted ${JSON.stringify(details)}\n`); browser.test.assertEq( "onCompleted", expecting.shift(), "got expected event" ); browser.test.assertEq( "localhost", details.proxyInfo.host, "proxy host" ); browser.test.assertEq(port, details.proxyInfo.port, "proxy port"); browser.test.assertEq("http", details.proxyInfo.type, "proxy type"); browser.test.assertEq( "", details.proxyInfo.username, "proxy username not set by onAuthRequired" ); browser.test.assertEq( undefined, details.proxyInfo.password, "no proxy password" ); browser.test.assertEq(expecting.length, 0, "got all expected events"); browser.test.sendMessage("done"); }, { urls: [""] } ); // Handle the proxy request. browser.proxy.onRequest.addListener( details => { browser.test.log(`onRequest ${JSON.stringify(details)}`); return [{ host: "localhost", port, type: "http" }]; }, { urls: [""] }, ["requestHeaders"] ); browser.test.sendMessage("ready"); } let handlingExt = getExtension(background); await handlingExt.startup(); await handlingExt.awaitMessage("ready"); authManager.clearAll(); let contentPage = await ExtensionTestUtils.loadContentPage( `http://mozilla.org/` ); await handlingExt.awaitMessage("done"); await contentPage.close(); await handlingExt.unload(); }); add_task(async function test_webRequest_auth_proxy_https() { async function background(port) { let authReceived = false; browser.webRequest.onBeforeSendHeaders.addListener( details => { if (authReceived) { browser.test.sendMessage("done"); return { cancel: true }; } }, { urls: [""] }, ["blocking"] ); browser.webRequest.onAuthRequired.addListener( details => { authReceived = true; return { authCredentials: { username: "puser", password: "ppass" } }; }, { urls: [""] }, ["blocking"] ); // Handle the proxy request. browser.proxy.onRequest.addListener( details => { browser.test.log(`onRequest ${JSON.stringify(details)}`); return [{ host: "localhost", port, type: "http" }]; }, { urls: [""] }, ["requestHeaders"] ); browser.test.sendMessage("ready"); } let handlingExt = getExtension(background); await handlingExt.startup(); await handlingExt.awaitMessage("ready"); authManager.clearAll(); let contentPage = await ExtensionTestUtils.loadContentPage( `https://407.example.com/` ); await handlingExt.awaitMessage("done"); await contentPage.close(); await handlingExt.unload(); }); add_task(async function test_webRequest_auth_proxy_system() { async function background(port) { browser.webRequest.onBeforeRequest.addListener( details => { browser.test.fail("onBeforeRequest"); }, { urls: [""] } ); browser.webRequest.onAuthRequired.addListener( details => { browser.test.sendMessage("onAuthRequired"); // cancel is silently ignored, if it were not (e.g someone messes up in // WebRequest.jsm and allows cancel) this test would fail. return { cancel: true, authCredentials: { username: "puser", password: "ppass" }, }; }, { urls: [""] }, ["blocking"] ); // Handle the proxy request. browser.proxy.onRequest.addListener( details => { browser.test.log(`onRequest ${JSON.stringify(details)}`); return { host: "localhost", port, type: "http" }; }, { urls: [""] } ); browser.test.sendMessage("ready"); } let handlingExt = getExtension(background); await handlingExt.startup(); await handlingExt.awaitMessage("ready"); authManager.clearAll(); function fetch(url) { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.mozBackgroundRequest = true; xhr.open("GET", url); xhr.onload = () => { resolve(xhr.responseText); }; xhr.onerror = () => { reject(xhr.status); }; xhr.send(); }); } await Promise.all([ handlingExt.awaitMessage("onAuthRequired"), fetch("http://mozilla.org"), ]); await handlingExt.unload(); });