summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html')
-rw-r--r--toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html181
1 files changed, 181 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html
new file mode 100644
index 0000000000..f260f040a1
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_auth.html
@@ -0,0 +1,181 @@
+<!DOCTYPE HTML>
+
+<html>
+<head>
+<meta charset="utf-8">
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script 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.
+
+let baseUrl = "http://mochi.test:8888/tests/toolkit/components/passwordmgr/test/mochitest/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();
+ });
+}
+
+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/*"]});
+ }
+
+ let permissions = [
+ "webRequest",
+ "*://mochi.test/*",
+ ];
+ if (blocking) {
+ permissions.push("webRequestBlocking");
+ }
+ return ExtensionTestUtils.loadExtension({
+ manifest: {
+ permissions,
+ },
+ background: `(${background})(${JSON.stringify(result)})`,
+ });
+}
+
+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(() => {
+ /* eslint-env mozilla/chrome-script */
+ let observer = channel => {
+ if (!(channel instanceof Ci.nsIHttpChannel && channel.URI.host === "mochi.test" &&
+ channel.URI.spec.includes("authenticate.sjs"))) {
+ return;
+ }
+ Services.obs.removeObserver(observer, "http-on-modify-request");
+ channel.notificationCallbacks = {
+ QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor",
+ "nsIAuthPromptProvider",
+ "nsIAuthPrompt2"]),
+ getInterface: ChromeUtils.generateQI(["nsIAuthPromptProvider",
+ "nsIAuthPrompt2"]),
+ promptAuth(channel, level, authInfo) {
+ throw Components.Exception("", 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 handlingExt = getAuthHandler();
+ await handlingExt.startup();
+
+ await Assert.rejects(testXHR(`${baseUrl}?realm=auth_nonblocking_forwardAuth&user=auth_nonblocking_forwardAuth&pass=auth_nonblocking_forwardAuth`),
+ ProgressEvent,
+ "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(() => {
+ /* eslint-env mozilla/chrome-script */
+ let observer = channel => {
+ if (!(channel instanceof Ci.nsIHttpChannel && channel.URI.host === "mochi.test" &&
+ channel.URI.spec.includes("authenticate.sjs"))) {
+ return;
+ }
+ Services.obs.removeObserver(observer, "http-on-modify-request");
+ channel.notificationCallbacks = {
+ QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor",
+ "nsIAuthPrompt2"]),
+ getInterface: ChromeUtils.generateQI(["nsIAuthPrompt2"]),
+ promptAuth(request, level, authInfo) {
+ throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
+ },
+ 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(() => {
+ request.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 handlingExt = getAuthHandler();
+ await handlingExt.startup();
+
+ await Assert.rejects(testXHR(`${baseUrl}?realm=auth_nonblocking_forwardAuthPromptProvider&user=auth_nonblocking_forwardAuth&pass=auth_nonblocking_forwardAuth`),
+ ProgressEvent,
+ "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();
+});
+</script>
+</head>
+<body>
+<div id="test">Authorization Test</div>
+
+</body>
+</html>