Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: win10_2009 OR win11_2009 OR os == 'android'
- Manifest: dom/webauthn/tests/mochitest.toml
<!DOCTYPE html>
<meta charset=utf-8>
<head>
<title>Test for aborting W3C Web Authentication request</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="u2futil.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>Test for aborting W3C Web Authentication request</h1>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1415675">Mozilla Bug 1415675</a>
<script class="testbody" type="text/javascript">
"use strict";
function arrivingHereIsBad(aResult) {
ok(false, "Bad result! Received a: " + aResult);
}
function expectAbortError(aResult) {
is(aResult.code, DOMException.ABORT_ERR, "Expecting an AbortError");
}
add_task(async () => {
// Enable USB tokens.
await SpecialPowers.pushPrefEnv({"set": [
["security.webauth.webauthn_enable_softtoken", false],
["security.webauth.webauthn_enable_usbtoken", true],
]});
});
// Start a new MakeCredential() request.
function requestMakeCredential(signal) {
let publicKey = {
rp: {id: document.domain, name: "none"},
user: {id: new Uint8Array(), name: "none", displayName: "none"},
challenge: crypto.getRandomValues(new Uint8Array(16)),
timeout: 5000, // the minimum timeout is actually 15 seconds
pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}],
};
return navigator.credentials.create({publicKey, signal});
}
// Start a new GetAssertion() request.
async function requestGetAssertion(signal) {
let newCredential = {
type: "public-key",
id: crypto.getRandomValues(new Uint8Array(16)),
transports: ["usb"],
};
let publicKey = {
challenge: crypto.getRandomValues(new Uint8Array(16)),
timeout: 5000, // the minimum timeout is actually 15 seconds
rpId: document.domain,
allowCredentials: [newCredential]
};
// Start the request, handle failures only.
return navigator.credentials.get({publicKey, signal});
}
// Create an AbortController and abort immediately.
add_task(async function test_create_abortcontroller_and_abort() {
let ctrl = new AbortController();
ctrl.abort();
// The event shouldn't fire.
ctrl.signal.onabort = arrivingHereIsBad;
// MakeCredential() should abort immediately.
await requestMakeCredential(ctrl.signal)
.then(arrivingHereIsBad)
.catch(expectAbortError);
// GetAssertion() should abort immediately.
await requestGetAssertion(ctrl.signal)
.then(arrivingHereIsBad)
.catch(expectAbortError);
});
// Request a new credential and abort the request.
add_task(async function test_request_credential_and_abort() {
let aborted = false;
let ctrl = new AbortController();
ctrl.signal.onabort = () => {
ok(!aborted, "abort event fired once");
aborted = true;
};
// Request a new credential.
let request = requestMakeCredential(ctrl.signal)
.then(arrivingHereIsBad)
.catch(err => {
ok(aborted, "abort event was fired");
expectAbortError(err);
});
// Wait a tick for the statemachine to start.
await Promise.resolve();
// Abort the request.
ok(!aborted, "request still pending");
ctrl.abort();
ok(aborted, "request aborted");
// Wait for the request to terminate.
await request;
});
// Request a new assertion and abort the request.
add_task(async function test_request_assertion_and_abort() {
let aborted = false;
let ctrl = new AbortController();
ctrl.signal.onabort = () => {
ok(!aborted, "abort event fired once");
aborted = true;
};
// Request a new assertion.
let request = requestGetAssertion(ctrl.signal)
.then(arrivingHereIsBad)
.catch(err => {
ok(aborted, "abort event was fired");
expectAbortError(err);
});
// Wait a tick for the statemachine to start.
await Promise.resolve();
// Abort the request.
ok(!aborted, "request still pending");
ctrl.abort();
ok(aborted, "request aborted");
// Wait for the request to terminate.
await request;
});
</script>
</body>
</html>