summaryrefslogtreecommitdiffstats
path: root/dom/webauthn/tests/browser/browser_abort_visibility.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webauthn/tests/browser/browser_abort_visibility.js')
-rw-r--r--dom/webauthn/tests/browser/browser_abort_visibility.js277
1 files changed, 277 insertions, 0 deletions
diff --git a/dom/webauthn/tests/browser/browser_abort_visibility.js b/dom/webauthn/tests/browser/browser_abort_visibility.js
new file mode 100644
index 0000000000..d8b2b5edcc
--- /dev/null
+++ b/dom/webauthn/tests/browser/browser_abort_visibility.js
@@ -0,0 +1,277 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const TEST_URL =
+ "https://example.com/browser/dom/webauthn/tests/browser/tab_webauthn_result.html";
+
+add_task(async function test_setup() {
+ return SpecialPowers.pushPrefEnv({
+ set: [
+ ["security.webauth.webauthn_enable_softtoken", false],
+ ["security.webauth.webauthn_enable_usbtoken", true],
+ ],
+ });
+});
+add_task(test_switch_tab);
+add_task(test_new_window_make);
+add_task(test_new_window_get);
+add_task(test_minimize_make);
+add_task(test_minimize_get);
+
+async function assertStatus(tab, expected) {
+ let actual = await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [],
+ async function () {
+ info("visbility state: " + content.document.visibilityState);
+ info("active: " + content.browsingContext.isActive);
+ return content.document.getElementById("status").value;
+ }
+ );
+ is(actual, expected, "webauthn request " + expected);
+}
+
+async function waitForStatus(tab, expected) {
+ /* eslint-disable no-shadow */
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [[expected]],
+ async function (expected) {
+ return ContentTaskUtils.waitForCondition(() => {
+ info(
+ "expecting " +
+ expected +
+ ", visbility state: " +
+ content.document.visibilityState
+ );
+ info(
+ "expecting " +
+ expected +
+ ", active: " +
+ content.browsingContext.isActive
+ );
+ return content.document.getElementById("status").value == expected;
+ });
+ }
+ );
+ /* eslint-enable no-shadow */
+
+ await assertStatus(tab, expected);
+}
+
+function startMakeCredentialRequest(tab) {
+ return SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ const cose_alg_ECDSA_w_SHA256 = -7;
+
+ let publicKey = {
+ rp: { id: content.document.domain, name: "none" },
+ user: {
+ id: new Uint8Array(),
+ name: "none",
+ displayName: "none",
+ },
+ challenge: content.crypto.getRandomValues(new Uint8Array(16)),
+ timeout: 5000, // the minimum timeout is actually 15 seconds
+ pubKeyCredParams: [{ type: "public-key", alg: cose_alg_ECDSA_w_SHA256 }],
+ };
+
+ let status = content.document.getElementById("status");
+
+ info(
+ "Attempting to create credential for origin: " +
+ content.document.nodePrincipal.origin
+ );
+ content.navigator.credentials
+ .create({ publicKey })
+ .then(() => {
+ status.value = "completed";
+ })
+ .catch(() => {
+ status.value = "aborted";
+ });
+
+ status.value = "pending";
+ });
+}
+
+function startGetAssertionRequest(tab) {
+ return SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let newCredential = {
+ type: "public-key",
+ id: content.crypto.getRandomValues(new Uint8Array(16)),
+ transports: ["usb"],
+ };
+
+ let publicKey = {
+ challenge: content.crypto.getRandomValues(new Uint8Array(16)),
+ timeout: 5000, // the minimum timeout is actually 15 seconds
+ rpId: content.document.domain,
+ allowCredentials: [newCredential],
+ };
+
+ let status = content.document.getElementById("status");
+
+ info(
+ "Attempting to get credential for origin: " +
+ content.document.nodePrincipal.origin
+ );
+ content.navigator.credentials
+ .get({ publicKey })
+ .then(() => {
+ status.value = "completed";
+ })
+ .catch(ex => {
+ info("aborted: " + ex);
+ status.value = "aborted";
+ });
+
+ status.value = "pending";
+ });
+}
+
+// Test that MakeCredential() and GetAssertion() requests
+// are aborted when the current tab loses its focus.
+async function test_switch_tab() {
+ // Create a new tab for the MakeCredential() request.
+ let tab_create = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_URL
+ );
+
+ // Start the request.
+ await startMakeCredentialRequest(tab_create);
+ await assertStatus(tab_create, "pending");
+
+ // Open another tab and switch to it. The first will lose focus.
+ let tab_get = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+ await assertStatus(tab_create, "pending");
+
+ // Start a GetAssertion() request in the second tab, the first is aborted
+ await startGetAssertionRequest(tab_get);
+ await waitForStatus(tab_create, "aborted");
+ await assertStatus(tab_get, "pending");
+
+ // Start a second request in the second tab. It should abort.
+ await startGetAssertionRequest(tab_get);
+ await waitForStatus(tab_get, "aborted");
+
+ // Close tabs.
+ BrowserTestUtils.removeTab(tab_create);
+ BrowserTestUtils.removeTab(tab_get);
+}
+
+function waitForWindowActive(win, active) {
+ return Promise.all([
+ BrowserTestUtils.waitForEvent(win, active ? "focus" : "blur"),
+ BrowserTestUtils.waitForEvent(win, active ? "activate" : "deactivate"),
+ ]);
+}
+
+async function test_new_window_make() {
+ // Create a new tab for the MakeCredential() request.
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+
+ // Start a MakeCredential request.
+ await startMakeCredentialRequest(tab);
+ await assertStatus(tab, "pending");
+
+ let windowGonePromise = waitForWindowActive(window, false);
+ // Open a new window. The tab will lose focus.
+ let win = await BrowserTestUtils.openNewBrowserWindow();
+ await windowGonePromise;
+ await assertStatus(tab, "pending");
+
+ let windowBackPromise = waitForWindowActive(window, true);
+ await BrowserTestUtils.closeWindow(win);
+ await windowBackPromise;
+
+ // Close tab.
+ await BrowserTestUtils.removeTab(tab);
+}
+
+async function test_new_window_get() {
+ // Create a new tab for the GetAssertion() request.
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+
+ // Start a GetAssertion request.
+ await startGetAssertionRequest(tab);
+ await assertStatus(tab, "pending");
+
+ let windowGonePromise = waitForWindowActive(window, false);
+ // Open a new window. The tab will lose focus.
+ let win = await BrowserTestUtils.openNewBrowserWindow();
+ await windowGonePromise;
+ await assertStatus(tab, "pending");
+
+ let windowBackPromise = waitForWindowActive(window, true);
+ await BrowserTestUtils.closeWindow(win);
+ await windowBackPromise;
+
+ // Close tab.
+ BrowserTestUtils.removeTab(tab);
+}
+
+async function test_minimize_make() {
+ // Minimizing windows doesn't supported in headless mode.
+ if (Services.env.get("MOZ_HEADLESS")) {
+ return;
+ }
+
+ // Create a new window for the MakeCredential() request.
+ let win = await BrowserTestUtils.openNewBrowserWindow();
+ let tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, TEST_URL);
+
+ // Start a MakeCredential request.
+ await startMakeCredentialRequest(tab);
+ await assertStatus(tab, "pending");
+
+ // Minimize the window.
+ let windowGonePromise = waitForWindowActive(win, false);
+ win.minimize();
+ await assertStatus(tab, "pending");
+ await windowGonePromise;
+
+ // Restore the window.
+ await new Promise(resolve => SimpleTest.waitForFocus(resolve, win));
+ await assertStatus(tab, "pending");
+
+ // Close window and wait for main window to be focused again.
+ let windowBackPromise = waitForWindowActive(window, true);
+ await BrowserTestUtils.removeTab(tab);
+ await BrowserTestUtils.closeWindow(win);
+ await windowBackPromise;
+}
+
+async function test_minimize_get() {
+ // Minimizing windows doesn't supported in headless mode.
+ if (Services.env.get("MOZ_HEADLESS")) {
+ return;
+ }
+
+ // Create a new window for the GetAssertion() request.
+ let win = await BrowserTestUtils.openNewBrowserWindow();
+ let tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, TEST_URL);
+
+ // Start a GetAssertion request.
+ await startGetAssertionRequest(tab);
+ await assertStatus(tab, "pending");
+
+ // Minimize the window.
+ let windowGonePromise = waitForWindowActive(win, false);
+ win.minimize();
+ await assertStatus(tab, "pending");
+ await windowGonePromise;
+
+ // Restore the window.
+ await new Promise(resolve => SimpleTest.waitForFocus(resolve, win));
+ await assertStatus(tab, "pending");
+
+ // Close window and wait for main window to be focused again.
+ let windowBackPromise = waitForWindowActive(window, true);
+ await BrowserTestUtils.removeTab(tab);
+ await BrowserTestUtils.closeWindow(win);
+ await windowBackPromise;
+}