1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 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() {
throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
},
getAuthPrompt() {
return this;
},
asyncPromptAuth(channel, callback, context) {
// 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() {
throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
},
asyncPromptAuth(request) {
// 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>
|