--- a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html
@@ -54,188 +54,16 @@ function getAuthHandler(result, blocking
return ExtensionTestUtils.loadExtension({
manifest: {
permissions,
},
background: `(${background})(${JSON.stringify(result)})`,
});
}
-add_task(async function test_webRequest_auth() {
- // Make use of head_webrequest to ensure event sequence.
- let events = {
- "onBeforeRequest": [{urls: ["*://mochi.test/*"]}, ["blocking"]],
- "onBeforeSendHeaders": [{urls: ["*://mochi.test/*"]}, ["blocking", "requestHeaders"]],
- "onSendHeaders": [{urls: ["*://mochi.test/*"]}, ["requestHeaders"]],
- "onBeforeRedirect": [{urls: ["*://mochi.test/*"]}],
- "onHeadersReceived": [{urls: ["*://mochi.test/*"]}, ["blocking", "responseHeaders"]],
- "onAuthRequired": [{urls: ["*://mochi.test/*"]}, ["blocking", "responseHeaders"]],
- "onResponseStarted": [{urls: ["*://mochi.test/*"]}],
- "onCompleted": [{urls: ["*://mochi.test/*"]}, ["responseHeaders"]],
- "onErrorOccurred": [{urls: ["*://mochi.test/*"]}],
- };
-
- let extension = makeExtension(events);
- await extension.startup();
- let authInfo = {
- username: "testuser",
- password: "testpass",
- };
- let expect = {
- "authenticate.sjs": {
- type: "xmlhttprequest",
- // we expect these additional events after onAuthRequired
- optional_events: ["onBeforeRequest", "onHeadersReceived"],
- authInfo,
- },
- };
- // expecting origin == undefined
- extension.sendMessage("set-expected", {expect, origin: location.href});
- await extension.awaitMessage("continue");
-
- await testXHR(`${baseUrl}?realm=webRequest_auth&user=${authInfo.username}&pass=${authInfo.password}`);
-
- await extension.awaitMessage("done");
- await extension.unload();
-});
-
-// This test is the same as above, however we shouldn't receive onAuthRequired
-// since those credentials are now cached (thus optional_events is not set).
-add_task(async function test_webRequest_cached_credentials() {
- // Make use of head_webrequest to ensure event sequence.
- let events = {
- "onBeforeRequest": [{urls: ["*://mochi.test/*"]}, ["blocking"]],
- "onBeforeSendHeaders": [{urls: ["*://mochi.test/*"]}, ["blocking", "requestHeaders"]],
- "onSendHeaders": [{urls: ["*://mochi.test/*"]}, ["requestHeaders"]],
- "onBeforeRedirect": [{urls: ["*://mochi.test/*"]}],
- "onHeadersReceived": [{urls: ["*://mochi.test/*"]}, ["blocking", "responseHeaders"]],
- "onAuthRequired": [{urls: ["*://mochi.test/*"]}, ["blocking", "responseHeaders"]],
- "onResponseStarted": [{urls: ["*://mochi.test/*"]}],
- "onCompleted": [{urls: ["*://mochi.test/*"]}, ["responseHeaders"]],
- "onErrorOccurred": [{urls: ["*://mochi.test/*"]}],
- };
-
- let extension = makeExtension(events);
- await extension.startup();
- let authInfo = {
- username: "testuser",
- password: "testpass",
- };
- let expect = {
- "authenticate.sjs": {
- type: "xmlhttprequest",
- events: ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders", "onHeadersReceived", "onResponseStarted", "onCompleted"],
- },
- };
- // expecting origin == undefined
- extension.sendMessage("set-expected", {expect, origin: location.href});
- await extension.awaitMessage("continue");
-
- await testXHR(`${baseUrl}?realm=webRequest_auth&user=${authInfo.username}&pass=${authInfo.password}`);
-
- await extension.awaitMessage("done");
- await extension.unload();
-});
-
-add_task(async function test_webRequest_cached_credentials2() {
- let authCredentials = {
- username: "testuser",
- password: "testpass",
- };
- let ex1 = getAuthHandler();
- await ex1.startup();
-
- await testXHR(`${baseUrl}?realm=webRequest_auth&user=${authCredentials.username}&pass=${authCredentials.password}`);
-
- await ex1.awaitMessage("onCompleted");
- await ex1.unload();
-});
-
-add_task(async function test_webRequest_window() {
- let authCredentials = {
- username: "testuser",
- password: "testpass",
- };
- let ex1 = getAuthHandler();
- await ex1.startup();
-
- let win = window.open(`${baseUrl}?realm=test_webRequest_window&user=${authCredentials.username}&pass=${authCredentials.password}`);
-
- await ex1.awaitMessage("onCompleted");
- await ex1.unload();
- win.close();
-});
-
-add_task(async function test_webRequest_auth_cancelled() {
- let authCredentials = {
- username: "testuser_canceled",
- password: "testpass_canceled",
- };
- let ex1 = getAuthHandler({authCredentials});
- await ex1.startup();
- let ex2 = getAuthHandler({cancel: true});
- await ex2.startup();
-
- await Assert.rejects(testXHR(`${baseUrl}?realm=test_webRequest_auth_cancelled&user=${authCredentials.username}&pass=${authCredentials.password}`), "caught rejected xhr");
-
- await Promise.all([
- ex1.awaitMessage("onAuthRequired"),
- ex2.awaitMessage("onAuthRequired"),
- ex1.awaitMessage("onErrorOccurred"),
- ex2.awaitMessage("onErrorOccurred"),
- ]);
- await ex1.unload();
- await ex2.unload();
-});
-
-add_task(async function test_webRequest_auth_nonblocking() {
- // The first listener handles the auth request, the second listener
- // is a non-blocking listener and cannot respond but will get the call.
- let authCredentials = {
- username: "foobar",
- password: "testpass",
- };
- let handlingExt = getAuthHandler({authCredentials});
- await handlingExt.startup();
- let extension = getAuthHandler({}, false);
- await extension.startup();
-
- await testXHR(`${baseUrl}?realm=webRequest_auth_nonblocking&user=${authCredentials.username}&pass=${authCredentials.password}`);
-
- await Promise.all([
- extension.awaitMessage("onAuthRequired"),
- extension.awaitMessage("onCompleted"),
- handlingExt.awaitMessage("onAuthRequired"),
- handlingExt.awaitMessage("onCompleted"),
- ]);
- await extension.unload();
- await handlingExt.unload();
-});
-
-
-add_task(async function test_webRequest_auth_blocking_noreturn() {
- // The first listener is blocking but doesn't return anything. The second
- // listener cancels the request.
- let ext = getAuthHandler();
- await ext.startup();
- let canceler = getAuthHandler({cancel: true});
- await canceler.startup();
-
- await Assert.rejects(testXHR(`${baseUrl}?realm=auth_blocking_noreturn&user=auth_blocking_noreturn&pass=auth_blocking_noreturn`), "caught rejected xhr");
-
- await Promise.all([
- ext.awaitMessage("onAuthRequired"),
- ext.awaitMessage("onErrorOccurred"),
- canceler.awaitMessage("onAuthRequired"),
- canceler.awaitMessage("onErrorOccurred"),
- ]);
- await ext.unload();
- await canceler.unload();
-});
-
add_task(async function test_webRequest_auth_nonblocking_forwardAuthProvider() {
// The chrome script sets up a default auth handler on the channel, the
// extension does not return anything in the authRequred call. We should
// get the call in the extension first, then in the chrome code where we
// cancel the request to avoid dealing with the prompt dialog here. The test
// is to ensure that WebRequest calls the previous notificationCallbacks
// if the authorization is not handled by the onAuthRequired handler.
@@ -307,24 +135,24 @@ add_task(async function test_webRequest_
if (!(channel instanceof Ci.nsIHttpChannel && channel.URI.host === "mochi.test")) {
return;
}
Services.obs.removeObserver(observer, "http-on-modify-request");
channel.notificationCallbacks = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor,
Ci.nsIAuthPrompt2]),
getInterface: XPCOMUtils.generateQI([Ci.nsIAuthPrompt2]),
- promptAuth(channel, level, authInfo) {
+ promptAuth(request, level, authInfo) {
throw Cr.NS_ERROR_NO_INTERFACE;
},
- asyncPromptAuth(channel, callback, context, level, authInfo) {
+ asyncPromptAuth(request, callback, context, level, authInfo) {
// We just cancel here, we're only ensuring that non-webrequest
// notificationcallbacks get called if webrequest doesn't handle it.
Promise.resolve().then(() => {
- channel.cancel(Cr.NS_BINDING_ABORTED);
+ request.cancel(Cr.NS_BINDING_ABORTED);
sendAsyncMessage("callback-complete");
});
},
};
};
Services.obs.addObserver(observer, "http-on-modify-request");
sendAsyncMessage("chrome-ready");
});
@@ -339,88 +167,15 @@ add_task(async function test_webRequest_
await callbackComplete;
await handlingExt.awaitMessage("onAuthRequired");
// We expect onErrorOccurred because the "default" authprompt above cancelled
// the auth request to avoid a dialog.
await handlingExt.awaitMessage("onErrorOccurred");
await handlingExt.unload();
chromeScript.destroy();
});
-
-add_task(async function test_webRequest_duelingAuth() {
- let exNone = getAuthHandler();
- await exNone.startup();
- let authCredentials = {
- username: "testuser_da1",
- password: "testpass_da1",
- };
- let ex1 = getAuthHandler({authCredentials});
- await ex1.startup();
- let exEmpty = getAuthHandler({});
- await exEmpty.startup();
- let ex2 = getAuthHandler({authCredentials: {
- username: "testuser_da2",
- password: "testpass_da2",
- }});
- await ex2.startup();
-
- // XHR should succeed since the first credentials win, and they are correct.
- await testXHR(`${baseUrl}?realm=test_webRequest_duelingAuth&user=${authCredentials.username}&pass=${authCredentials.password}`);
-
- await Promise.all([
- exNone.awaitMessage("onAuthRequired"),
- exNone.awaitMessage("onCompleted"),
- exEmpty.awaitMessage("onAuthRequired"),
- exEmpty.awaitMessage("onCompleted"),
- ex1.awaitMessage("onAuthRequired"),
- ex1.awaitMessage("onCompleted"),
- ex2.awaitMessage("onAuthRequired"),
- ex2.awaitMessage("onCompleted"),
- ]);
- await Promise.all([
- exNone.unload(),
- exEmpty.unload(),
- ex1.unload(),
- ex2.unload(),
- ]);
-});
-
-add_task(async function test_webRequest_auth_proxy() {
- function background() {
- let proxyOk = false;
- browser.webRequest.onAuthRequired.addListener((details) => {
- browser.test.succeed(`handlingExt onAuthRequired called with ${details.requestId} ${details.url}`);
- if (details.isProxy) {
- browser.test.succeed("providing proxy authorization");
- proxyOk = true;
- return {authCredentials: {username: "puser", password: "ppass"}};
- }
- browser.test.assertTrue(proxyOk, "providing www authorization after proxy auth");
- browser.test.sendMessage("done");
- return {authCredentials: {username: "auser", password: "apass"}};
- }, {urls: ["*://mochi.test/*"]}, ["blocking"]);
- }
-
- let handlingExt = ExtensionTestUtils.loadExtension({
- manifest: {
- permissions: [
- "webRequest",
- "webRequestBlocking",
- "*://mochi.test/*",
- ],
- },
- background,
- });
-
- await handlingExt.startup();
-
- await testXHR(`${baseUrl}?realm=auth_proxy&user=auser&pass=apass&proxy_user=puser&proxy_pass=ppass`);
-
- await handlingExt.awaitMessage("done");
- await handlingExt.unload();
-});
</script>
</head>
<body>
<div id="test">Authorization Test</div>
</body>
</html>
copy from toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html
copy to toolkit/components/extensions/test/xpcshell/test_ext_webRequest_auth.js
--- a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_auth.js
@@ -1,426 +1,384 @@
-<!DOCTYPE HTML>
-
-<html>
-<head>
-<meta charset="utf-8">
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
- <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
- <script type="text/javascript" src="head_webrequest.js"></script>
- <script type="text/javascript" src="head.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-<script>
"use strict";
-// This file defines content scripts.
-/* eslint-env mozilla/frame-script */
+Cu.importGlobalProperties(["URL"]);
+
+const HOSTS = new Set([
+ "example.com",
+]);
+
+const server = createHttpServer({hosts: HOSTS});
-let baseUrl = "http://mochi.test:8888/tests/toolkit/components/passwordmgr/test/authenticate.sjs";
-function testXHR(url) {
- return new Promise((resolve, reject) => {
- let xhr = new XMLHttpRequest();
- xhr.open("GET", url);
- xhr.onload = resolve;
- xhr.onabort = reject;
- xhr.onerror = reject;
- xhr.send();
- });
-}
+const BASE_URL = "http://example.com";
+
+// Save seen realms for cache checking.
+let realms = new Set([]);
+
+server.registerPathHandler("/authenticate.sjs", (request, response) => {
+ let url = new URL(`${BASE_URL}${request.path}?${request.queryString}`);
+ let realm = url.searchParams.get("realm") || "mochitest";
+ let proxy_realm = url.searchParams.get("proxy_realm");
-function getAuthHandler(result, blocking = true) {
- function background(result) {
- browser.webRequest.onAuthRequired.addListener((details) => {
- browser.test.succeed(`authHandler.onAuthRequired called with ${details.requestId} ${details.url} result ${JSON.stringify(result)}`);
- browser.test.sendMessage("onAuthRequired");
- return result;
- }, {urls: ["*://mochi.test/*"]}, ["blocking"]);
- browser.webRequest.onCompleted.addListener((details) => {
- browser.test.succeed(`authHandler.onCompleted called with ${details.requestId} ${details.url}`);
- browser.test.sendMessage("onCompleted");
- }, {urls: ["*://mochi.test/*"]});
- browser.webRequest.onErrorOccurred.addListener((details) => {
- browser.test.succeed(`authHandler.onErrorOccurred called with ${details.requestId} ${details.url}`);
- browser.test.sendMessage("onErrorOccurred");
- }, {urls: ["*://mochi.test/*"]});
+ function checkAuthorization(authorization) {
+ let expected_user = url.searchParams.get("user");
+ if (!expected_user) {
+ return true;
+ }
+ let expected_pass = url.searchParams.get("pass");
+ let actual_user, actual_pass;
+ let authHeader = request.getHeader("Authorization");
+ let match = /Basic (.+)/.exec(authHeader);
+ if (match.length != 2) {
+ throw new Error("Couldn't parse auth header: " + authHeader);
+ }
+ let userpass = atob(match[1]); // no atob() :-(
+ match = /(.*):(.*)/.exec(userpass);
+ if (match.length != 3) {
+ throw new Error("Couldn't decode auth header: " + userpass);
+ }
+ actual_user = match[1];
+ actual_pass = match[2];
+ return expected_user === actual_user && expected_pass === actual_pass;
}
- let permissions = [
- "webRequest",
- "*://mochi.test/*",
- ];
- if (blocking) {
- permissions.push("webRequestBlocking");
+ response.setHeader("Content-Type", "text/plain; charset=UTF-8", false);
+ if (proxy_realm && !request.hasHeader("Proxy-Authorization")) {
+ // We're not testing anything that requires checking the proxy auth user/password.
+ response.setStatusLine("1.0", 407, "Proxy authentication required");
+ response.setHeader("Proxy-Authenticate", `basic realm="${proxy_realm}"`, true);
+ response.write("proxy auth required");
+ } else if (!(realms.has(realm) && request.hasHeader("Authorization") && checkAuthorization())) {
+ realms.add(realm);
+ response.setStatusLine(request.httpVersion, 401, "Authentication required");
+ response.setHeader("WWW-Authenticate", `basic realm="${realm}"`, true);
+ response.write("auth required");
+ } else {
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.write("ok, got authorization");
}
+});
+
+function getExtension(bgConfig) {
+ function background(config) {
+ let path = config.path;
+ browser.webRequest.onBeforeRequest.addListener((details) => {
+ browser.test.log(`onBeforeRequest called with ${details.requestId} ${details.url}`);
+ browser.test.sendMessage("onBeforeRequest");
+ return config.onBeforeRequest.hasOwnProperty("result") && config.onBeforeRequest.result;
+ }, {urls: [path]}, config.onBeforeRequest.hasOwnProperty("extra") ? config.onBeforeRequest.extra : []);
+ browser.webRequest.onAuthRequired.addListener((details) => {
+ browser.test.log(`onAuthRequired called with ${details.requestId} ${details.url}`);
+ browser.test.assertEq(config.realm, details.realm, "providing www authorization");
+ browser.test.sendMessage("onAuthRequired");
+ return config.onAuthRequired.hasOwnProperty("result") && config.onAuthRequired.result;
+ }, {urls: [path]}, config.onAuthRequired.hasOwnProperty("extra") ? config.onAuthRequired.extra : []);
+ browser.webRequest.onCompleted.addListener((details) => {
+ browser.test.log(`onCompleted called with ${details.requestId} ${details.url}`);
+ browser.test.sendMessage("onCompleted");
+ }, {urls: [path]});
+ browser.webRequest.onErrorOccurred.addListener((details) => {
+ browser.test.log(`onErrorOccurred called with ${JSON.stringify(details)}`);
+ browser.test.sendMessage("onErrorOccurred");
+ }, {urls: [path]});
+ }
+
return ExtensionTestUtils.loadExtension({
manifest: {
- permissions,
+ permissions: [
+ "webRequest",
+ "webRequestBlocking",
+ bgConfig.path,
+ ],
},
- background: `(${background})(${JSON.stringify(result)})`,
+ background: `(${background})(${JSON.stringify(bgConfig)})`,
});
}
add_task(async function test_webRequest_auth() {
- // Make use of head_webrequest to ensure event sequence.
- let events = {
- "onBeforeRequest": [{urls: ["*://mochi.test/*"]}, ["blocking"]],
- "onBeforeSendHeaders": [{urls: ["*://mochi.test/*"]}, ["blocking", "requestHeaders"]],
- "onSendHeaders": [{urls: ["*://mochi.test/*"]}, ["requestHeaders"]],
- "onBeforeRedirect": [{urls: ["*://mochi.test/*"]}],
- "onHeadersReceived": [{urls: ["*://mochi.test/*"]}, ["blocking", "responseHeaders"]],
- "onAuthRequired": [{urls: ["*://mochi.test/*"]}, ["blocking", "responseHeaders"]],
- "onResponseStarted": [{urls: ["*://mochi.test/*"]}],
- "onCompleted": [{urls: ["*://mochi.test/*"]}, ["responseHeaders"]],
- "onErrorOccurred": [{urls: ["*://mochi.test/*"]}],
+ let config = {
+ path: `${BASE_URL}/*`,
+ realm: `webRequest_auth${Math.random()}`,
+ onBeforeRequest: {
+ extra: ["blocking"],
+ },
+ onAuthRequired: {
+ extra: ["blocking"],
+ result: {
+ authCredentials: {
+ username: "testuser",
+ password: "testpass",
+ },
+ },
+ },
};
- let extension = makeExtension(events);
+ let extension = getExtension(config);
await extension.startup();
- let authInfo = {
- username: "testuser",
- password: "testpass",
- };
- let expect = {
- "authenticate.sjs": {
- type: "xmlhttprequest",
- // we expect these additional events after onAuthRequired
- optional_events: ["onBeforeRequest", "onHeadersReceived"],
- authInfo,
- },
- };
- // expecting origin == undefined
- extension.sendMessage("set-expected", {expect, origin: location.href});
- await extension.awaitMessage("continue");
- await testXHR(`${baseUrl}?realm=webRequest_auth&user=${authInfo.username}&pass=${authInfo.password}`);
+ let requestUrl = `${BASE_URL}/authenticate.sjs?realm=${config.realm}`;
+ let contentPage = await ExtensionTestUtils.loadContentPage(requestUrl);
+ await Promise.all([
+ extension.awaitMessage("onBeforeRequest"),
+ extension.awaitMessage("onAuthRequired").then(() => {
+ return Promise.all([
+ extension.awaitMessage("onBeforeRequest"),
+ extension.awaitMessage("onCompleted"),
+ ]);
+ }),
+ ]);
+ await contentPage.close();
- await extension.awaitMessage("done");
+ // Second time around to test cached credentials
+ contentPage = await ExtensionTestUtils.loadContentPage(requestUrl);
+ await Promise.all([
+ extension.awaitMessage("onBeforeRequest"),
+ extension.awaitMessage("onCompleted"),
+ ]);
+
+ await contentPage.close();
await extension.unload();
});
-// This test is the same as above, however we shouldn't receive onAuthRequired
-// since those credentials are now cached (thus optional_events is not set).
-add_task(async function test_webRequest_cached_credentials() {
- // Make use of head_webrequest to ensure event sequence.
- let events = {
- "onBeforeRequest": [{urls: ["*://mochi.test/*"]}, ["blocking"]],
- "onBeforeSendHeaders": [{urls: ["*://mochi.test/*"]}, ["blocking", "requestHeaders"]],
- "onSendHeaders": [{urls: ["*://mochi.test/*"]}, ["requestHeaders"]],
- "onBeforeRedirect": [{urls: ["*://mochi.test/*"]}],
- "onHeadersReceived": [{urls: ["*://mochi.test/*"]}, ["blocking", "responseHeaders"]],
- "onAuthRequired": [{urls: ["*://mochi.test/*"]}, ["blocking", "responseHeaders"]],
- "onResponseStarted": [{urls: ["*://mochi.test/*"]}],
- "onCompleted": [{urls: ["*://mochi.test/*"]}, ["responseHeaders"]],
- "onErrorOccurred": [{urls: ["*://mochi.test/*"]}],
- };
-
- let extension = makeExtension(events);
- await extension.startup();
- let authInfo = {
- username: "testuser",
- password: "testpass",
- };
- let expect = {
- "authenticate.sjs": {
- type: "xmlhttprequest",
- events: ["onBeforeRequest", "onBeforeSendHeaders", "onSendHeaders", "onHeadersReceived", "onResponseStarted", "onCompleted"],
+add_task(async function test_webRequest_auth_cancelled() {
+ // Test that any auth listener can cancel.
+ let config = {
+ path: `${BASE_URL}/*`,
+ realm: `webRequest_auth${Math.random()}`,
+ onBeforeRequest: {
+ extra: ["blocking"],
+ },
+ onAuthRequired: {
+ extra: ["blocking"],
+ result: {
+ authCredentials: {
+ username: "testuser",
+ password: "testpass",
+ },
+ },
},
};
- // expecting origin == undefined
- extension.sendMessage("set-expected", {expect, origin: location.href});
- await extension.awaitMessage("continue");
- await testXHR(`${baseUrl}?realm=webRequest_auth&user=${authInfo.username}&pass=${authInfo.password}`);
-
- await extension.awaitMessage("done");
- await extension.unload();
-});
-
-add_task(async function test_webRequest_cached_credentials2() {
- let authCredentials = {
- username: "testuser",
- password: "testpass",
- };
- let ex1 = getAuthHandler();
+ let ex1 = getExtension(config);
+ config.onAuthRequired.result = {cancel: true};
+ let ex2 = getExtension(config);
await ex1.startup();
-
- await testXHR(`${baseUrl}?realm=webRequest_auth&user=${authCredentials.username}&pass=${authCredentials.password}`);
-
- await ex1.awaitMessage("onCompleted");
- await ex1.unload();
-});
-
-add_task(async function test_webRequest_window() {
- let authCredentials = {
- username: "testuser",
- password: "testpass",
- };
- let ex1 = getAuthHandler();
- await ex1.startup();
-
- let win = window.open(`${baseUrl}?realm=test_webRequest_window&user=${authCredentials.username}&pass=${authCredentials.password}`);
-
- await ex1.awaitMessage("onCompleted");
- await ex1.unload();
- win.close();
-});
-
-add_task(async function test_webRequest_auth_cancelled() {
- let authCredentials = {
- username: "testuser_canceled",
- password: "testpass_canceled",
- };
- let ex1 = getAuthHandler({authCredentials});
- await ex1.startup();
- let ex2 = getAuthHandler({cancel: true});
await ex2.startup();
- await Assert.rejects(testXHR(`${baseUrl}?realm=test_webRequest_auth_cancelled&user=${authCredentials.username}&pass=${authCredentials.password}`), "caught rejected xhr");
-
+ let requestUrl = `${BASE_URL}/authenticate.sjs?realm=${config.realm}`;
+ let contentPage = await ExtensionTestUtils.loadContentPage(requestUrl);
await Promise.all([
+ ex1.awaitMessage("onBeforeRequest"),
ex1.awaitMessage("onAuthRequired"),
+ ex1.awaitMessage("onErrorOccurred"),
+ ex2.awaitMessage("onBeforeRequest"),
ex2.awaitMessage("onAuthRequired"),
- ex1.awaitMessage("onErrorOccurred"),
ex2.awaitMessage("onErrorOccurred"),
]);
+
+ await contentPage.close();
await ex1.unload();
await ex2.unload();
});
+
add_task(async function test_webRequest_auth_nonblocking() {
- // The first listener handles the auth request, the second listener
- // is a non-blocking listener and cannot respond but will get the call.
- let authCredentials = {
- username: "foobar",
- password: "testpass",
+ let config = {
+ path: `${BASE_URL}/*`,
+ realm: `webRequest_auth${Math.random()}`,
+ onBeforeRequest: {
+ extra: ["blocking"],
+ },
+ onAuthRequired: {
+ extra: ["blocking"],
+ result: {
+ authCredentials: {
+ username: "testuser",
+ password: "testpass",
+ },
+ },
+ },
};
- let handlingExt = getAuthHandler({authCredentials});
- await handlingExt.startup();
- let extension = getAuthHandler({}, false);
- await extension.startup();
- await testXHR(`${baseUrl}?realm=webRequest_auth_nonblocking&user=${authCredentials.username}&pass=${authCredentials.password}`);
+ let ex1 = getExtension(config);
+ // non-blocking ext tries to cancel but cannot.
+ delete config.onBeforeRequest.extra;
+ delete config.onAuthRequired.extra;
+ config.onAuthRequired.result = {cancel: true};
+ let ex2 = getExtension(config);
+ await ex1.startup();
+ await ex2.startup();
+ let requestUrl = `${BASE_URL}/authenticate.sjs?realm=${config.realm}`;
+ let contentPage = await ExtensionTestUtils.loadContentPage(requestUrl);
await Promise.all([
- extension.awaitMessage("onAuthRequired"),
- extension.awaitMessage("onCompleted"),
- handlingExt.awaitMessage("onAuthRequired"),
- handlingExt.awaitMessage("onCompleted"),
+ ex1.awaitMessage("onBeforeRequest"),
+ ex1.awaitMessage("onAuthRequired").then(() => {
+ return Promise.all([
+ ex1.awaitMessage("onBeforeRequest"),
+ ex1.awaitMessage("onCompleted"),
+ ]);
+ }),
+ ex2.awaitMessage("onBeforeRequest"),
+ ex2.awaitMessage("onAuthRequired").then(() => {
+ return Promise.all([
+ ex2.awaitMessage("onBeforeRequest"),
+ ex2.awaitMessage("onCompleted"),
+ ]);
+ }),
]);
- await extension.unload();
- await handlingExt.unload();
+
+ await contentPage.close();
+ Services.obs.notifyObservers(null, "net:clear-active-logins");
+ await ex1.unload();
+ await ex2.unload();
});
-
add_task(async function test_webRequest_auth_blocking_noreturn() {
// The first listener is blocking but doesn't return anything. The second
// listener cancels the request.
- let ext = getAuthHandler();
- await ext.startup();
- let canceler = getAuthHandler({cancel: true});
- await canceler.startup();
-
- await Assert.rejects(testXHR(`${baseUrl}?realm=auth_blocking_noreturn&user=auth_blocking_noreturn&pass=auth_blocking_noreturn`), "caught rejected xhr");
-
- await Promise.all([
- ext.awaitMessage("onAuthRequired"),
- ext.awaitMessage("onErrorOccurred"),
- canceler.awaitMessage("onAuthRequired"),
- canceler.awaitMessage("onErrorOccurred"),
- ]);
- await ext.unload();
- await canceler.unload();
-});
-
-add_task(async function test_webRequest_auth_nonblocking_forwardAuthProvider() {
- // The chrome script sets up a default auth handler on the channel, the
- // extension does not return anything in the authRequred call. We should
- // get the call in the extension first, then in the chrome code where we
- // cancel the request to avoid dealing with the prompt dialog here. The test
- // is to ensure that WebRequest calls the previous notificationCallbacks
- // if the authorization is not handled by the onAuthRequired handler.
-
- let chromeScript = SpecialPowers.loadChromeScript(() => {
- ChromeUtils.import("resource://gre/modules/Services.jsm");
- ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
- let observer = channel => {
- if (!(channel instanceof Ci.nsIHttpChannel && channel.URI.host === "mochi.test")) {
- return;
- }
- Services.obs.removeObserver(observer, "http-on-modify-request");
- channel.notificationCallbacks = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor,
- Ci.nsIAuthPromptProvider,
- Ci.nsIAuthPrompt2]),
- getInterface: XPCOMUtils.generateQI([Ci.nsIAuthPromptProvider,
- Ci.nsIAuthPrompt2]),
- promptAuth(channel, level, authInfo) {
- throw Cr.NS_ERROR_NO_INTERFACE;
- },
- getAuthPrompt(reason, iid) {
- return this;
- },
- asyncPromptAuth(channel, callback, context, level, authInfo) {
- // We just cancel here, we're only ensuring that non-webrequest
- // notificationcallbacks get called if webrequest doesn't handle it.
- Promise.resolve().then(() => {
- callback.onAuthCancelled(context, false);
- channel.cancel(Cr.NS_BINDING_ABORTED);
- sendAsyncMessage("callback-complete");
- });
- },
- };
- };
- Services.obs.addObserver(observer, "http-on-modify-request");
- sendAsyncMessage("chrome-ready");
- });
- await chromeScript.promiseOneMessage("chrome-ready");
- let callbackComplete = chromeScript.promiseOneMessage("callback-complete");
+ let config = {
+ path: `${BASE_URL}/*`,
+ realm: `webRequest_auth${Math.random()}`,
+ onBeforeRequest: {
+ extra: ["blocking"],
+ },
+ onAuthRequired: {
+ extra: ["blocking"],
+ },
+ };
- let handlingExt = getAuthHandler();
- await handlingExt.startup();
-
- await Assert.rejects(testXHR(`${baseUrl}?realm=auth_nonblocking_forwardAuth&user=auth_nonblocking_forwardAuth&pass=auth_nonblocking_forwardAuth`), "caught rejected xhr");
-
- await callbackComplete;
- await handlingExt.awaitMessage("onAuthRequired");
- // We expect onErrorOccurred because the "default" authprompt above cancelled
- // the auth request to avoid a dialog.
- await handlingExt.awaitMessage("onErrorOccurred");
- await handlingExt.unload();
- chromeScript.destroy();
-});
-
-add_task(async function test_webRequest_auth_nonblocking_forwardAuthPrompt2() {
- // The chrome script sets up a default auth handler on the channel, the
- // extension does not return anything in the authRequred call. We should
- // get the call in the extension first, then in the chrome code where we
- // cancel the request to avoid dealing with the prompt dialog here. The test
- // is to ensure that WebRequest calls the previous notificationCallbacks
- // if the authorization is not handled by the onAuthRequired handler.
-
- let chromeScript = SpecialPowers.loadChromeScript(() => {
- ChromeUtils.import("resource://gre/modules/Services.jsm");
- ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ let ex1 = getExtension(config);
+ config.onAuthRequired.result = {cancel: true};
+ let ex2 = getExtension(config);
+ await ex1.startup();
+ await ex2.startup();
- let observer = channel => {
- if (!(channel instanceof Ci.nsIHttpChannel && channel.URI.host === "mochi.test")) {
- return;
- }
- Services.obs.removeObserver(observer, "http-on-modify-request");
- channel.notificationCallbacks = {
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor,
- Ci.nsIAuthPrompt2]),
- getInterface: XPCOMUtils.generateQI([Ci.nsIAuthPrompt2]),
- promptAuth(channel, level, authInfo) {
- throw Cr.NS_ERROR_NO_INTERFACE;
- },
- asyncPromptAuth(channel, callback, context, level, authInfo) {
- // We just cancel here, we're only ensuring that non-webrequest
- // notificationcallbacks get called if webrequest doesn't handle it.
- Promise.resolve().then(() => {
- channel.cancel(Cr.NS_BINDING_ABORTED);
- sendAsyncMessage("callback-complete");
- });
- },
- };
- };
- Services.obs.addObserver(observer, "http-on-modify-request");
- sendAsyncMessage("chrome-ready");
- });
- await chromeScript.promiseOneMessage("chrome-ready");
- let callbackComplete = chromeScript.promiseOneMessage("callback-complete");
+ let requestUrl = `${BASE_URL}/authenticate.sjs?realm=${config.realm}`;
+ let contentPage = await ExtensionTestUtils.loadContentPage(requestUrl);
+ await Promise.all([
+ ex1.awaitMessage("onBeforeRequest"),
+ ex1.awaitMessage("onAuthRequired"),
+ ex1.awaitMessage("onErrorOccurred"),
+ ex2.awaitMessage("onBeforeRequest"),
+ ex2.awaitMessage("onAuthRequired"),
+ ex2.awaitMessage("onErrorOccurred"),
+ ]);
- let handlingExt = getAuthHandler();
- await handlingExt.startup();
-
- await Assert.rejects(testXHR(`${baseUrl}?realm=auth_nonblocking_forwardAuthPromptProvider&user=auth_nonblocking_forwardAuth&pass=auth_nonblocking_forwardAuth`), "caught rejected xhr");
-
- await callbackComplete;
- await handlingExt.awaitMessage("onAuthRequired");
- // We expect onErrorOccurred because the "default" authprompt above cancelled
- // the auth request to avoid a dialog.
- await handlingExt.awaitMessage("onErrorOccurred");
- await handlingExt.unload();
- chromeScript.destroy();
+ await contentPage.close();
+ await ex1.unload();
+ await ex2.unload();
});
add_task(async function test_webRequest_duelingAuth() {
- let exNone = getAuthHandler();
- await exNone.startup();
- let authCredentials = {
- username: "testuser_da1",
- password: "testpass_da1",
+ let config = {
+ path: `${BASE_URL}/*`,
+ realm: `webRequest_auth${Math.random()}`,
+ onBeforeRequest: {
+ extra: ["blocking"],
+ },
+ onAuthRequired: {
+ extra: ["blocking"],
+ },
};
- let ex1 = getAuthHandler({authCredentials});
+ let exNone = getExtension(config);
+ await exNone.startup();
+
+ let authCredentials = {
+ username: `testuser_da1${Math.random()}`,
+ password: `testpass_da1${Math.random()}`,
+ };
+ config.onAuthRequired.result = {authCredentials};
+ let ex1 = getExtension(config);
await ex1.startup();
- let exEmpty = getAuthHandler({});
+
+ config.onAuthRequired.result = {};
+ let exEmpty = getExtension(config);
await exEmpty.startup();
- let ex2 = getAuthHandler({authCredentials: {
- username: "testuser_da2",
- password: "testpass_da2",
- }});
+
+ config.onAuthRequired.result = {
+ authCredentials: {
+ username: `testuser_da2${Math.random()}`,
+ password: `testpass_da2${Math.random()}`,
+ },
+ };
+ let ex2 = getExtension(config);
await ex2.startup();
- // XHR should succeed since the first credentials win, and they are correct.
- await testXHR(`${baseUrl}?realm=test_webRequest_duelingAuth&user=${authCredentials.username}&pass=${authCredentials.password}`);
+
+ let requestUrl = `${BASE_URL}/authenticate.sjs?realm=${config.realm}&user=${authCredentials.username}&pass=${authCredentials.password}`;
+ let contentPage = await ExtensionTestUtils.loadContentPage(requestUrl);
+ await Promise.all([
+ exNone.awaitMessage("onBeforeRequest"),
+ exNone.awaitMessage("onAuthRequired").then(() => {
+ return Promise.all([
+ exNone.awaitMessage("onBeforeRequest"),
+ exNone.awaitMessage("onCompleted"),
+ ]);
+ }),
+ exEmpty.awaitMessage("onBeforeRequest"),
+ exEmpty.awaitMessage("onAuthRequired").then(() => {
+ return Promise.all([
+ exEmpty.awaitMessage("onBeforeRequest"),
+ exEmpty.awaitMessage("onCompleted"),
+ ]);
+ }),
+ ex1.awaitMessage("onBeforeRequest"),
+ ex1.awaitMessage("onAuthRequired").then(() => {
+ return Promise.all([
+ ex1.awaitMessage("onBeforeRequest"),
+ ex1.awaitMessage("onCompleted"),
+ ]);
+ }),
+ ex2.awaitMessage("onBeforeRequest"),
+ ex2.awaitMessage("onAuthRequired").then(() => {
+ return Promise.all([
+ ex2.awaitMessage("onBeforeRequest"),
+ ex2.awaitMessage("onCompleted"),
+ ]);
+ }),
+ ]);
await Promise.all([
- exNone.awaitMessage("onAuthRequired"),
- exNone.awaitMessage("onCompleted"),
- exEmpty.awaitMessage("onAuthRequired"),
- exEmpty.awaitMessage("onCompleted"),
- ex1.awaitMessage("onAuthRequired"),
- ex1.awaitMessage("onCompleted"),
- ex2.awaitMessage("onAuthRequired"),
- ex2.awaitMessage("onCompleted"),
- ]);
- await Promise.all([
+ await contentPage.close(),
exNone.unload(),
exEmpty.unload(),
ex1.unload(),
ex2.unload(),
]);
});
add_task(async function test_webRequest_auth_proxy() {
- function background() {
+ function background(permissionPath) {
let proxyOk = false;
browser.webRequest.onAuthRequired.addListener((details) => {
- browser.test.succeed(`handlingExt onAuthRequired called with ${details.requestId} ${details.url}`);
+ browser.test.log(`handlingExt onAuthRequired called with ${details.requestId} ${details.url}`);
if (details.isProxy) {
browser.test.succeed("providing proxy authorization");
proxyOk = true;
return {authCredentials: {username: "puser", password: "ppass"}};
}
browser.test.assertTrue(proxyOk, "providing www authorization after proxy auth");
browser.test.sendMessage("done");
return {authCredentials: {username: "auser", password: "apass"}};
- }, {urls: ["*://mochi.test/*"]}, ["blocking"]);
+ }, {urls: [permissionPath]}, ["blocking"]);
}
let handlingExt = ExtensionTestUtils.loadExtension({
manifest: {
permissions: [
"webRequest",
"webRequestBlocking",
- "*://mochi.test/*",
+ `${BASE_URL}/*`,
],
},
- background,
+ background: `(${background})("${BASE_URL}/*")`,
});
await handlingExt.startup();
- await testXHR(`${baseUrl}?realm=auth_proxy&user=auser&pass=apass&proxy_user=puser&proxy_pass=ppass`);
+ let requestUrl = `${BASE_URL}/authenticate.sjs?realm=webRequest_auth${Math.random()}&proxy_realm=proxy_auth${Math.random()}`;
+ let contentPage = await ExtensionTestUtils.loadContentPage(requestUrl);
await handlingExt.awaitMessage("done");
+ await contentPage.close();
await handlingExt.unload();
});
-</script>
-</head>
-<body>
-<div id="test">Authorization Test</div>
-
-</body>
-</html>