/* 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";
let AboutWebauthnService = null;
var AboutWebauthnManagerJS = {
_topic: "about-webauthn-prompt",
_initialized: false,
_l10n: null,
_bio_l10n: null,
_curr_data: null,
_current_tab: "",
_previous_tab: "",
init() {
if (this._initialized) {
return;
}
this._l10n = new Localization(["toolkit/about/aboutWebauthn.ftl"], true);
this._bio_l10n = new Map();
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpGood",
"about-webauthn-ctap2-enroll-feedback-good"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpTooHigh",
"about-webauthn-ctap2-enroll-feedback-too-high"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpTooLow",
"about-webauthn-ctap2-enroll-feedback-too-low"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpTooLeft",
"about-webauthn-ctap2-enroll-feedback-too-left"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpTooRight",
"about-webauthn-ctap2-enroll-feedback-too-right"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpTooFast",
"about-webauthn-ctap2-enroll-feedback-too-fast"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpTooSlow",
"about-webauthn-ctap2-enroll-feedback-too-slow"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpPoorQuality",
"about-webauthn-ctap2-enroll-feedback-poor-quality"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpTooSkewed",
"about-webauthn-ctap2-enroll-feedback-too-skewed"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpTooShort",
"about-webauthn-ctap2-enroll-feedback-too-short"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpMergeFailure",
"about-webauthn-ctap2-enroll-feedback-merge-failure"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackFpExists",
"about-webauthn-ctap2-enroll-feedback-exists"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackNoUserActivity",
"about-webauthn-ctap2-enroll-feedback-no-user-activity"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackNoUserPresenceTransition",
"about-webauthn-ctap2-enroll-feedback-no-user-presence-transition"
);
this._bio_l10n.set(
"Ctap2EnrollFeedbackOther",
"about-webauthn-ctap2-enroll-feedback-other"
);
Services.obs.addObserver(this, this._topic);
this._initialized = true;
reset_page();
},
uninit() {
Services.obs.removeObserver(this, this._topic);
this._initialized = false;
this._l10n = null;
this._current_tab = "";
this._previous_tab = "";
},
observe(aSubject, aTopic, aData) {
let data = JSON.parse(aData);
// We have token
if (data.type == "selected-device") {
this._curr_data = data.auth_info;
this.show_ui_based_on_authenticator_info(data);
fake_click_event_for_id("info-tab-button");
} else if (data.type == "select-device") {
set_info_text("about-webauthn-text-select-device");
} else if (data.type == "pin-required") {
open_pin_required_tab();
} else if (data.type == "pin-invalid") {
let retries = data.retries ? data.retries : 0;
show_results_banner(
"error",
"about-webauthn-results-pin-invalid-error",
JSON.stringify({ retriesLeft: retries })
);
open_pin_required_tab();
} else if (data.type == "bio-enrollment-update") {
if (data.result.EnrollmentList) {
show_results_banner("success", "about-webauthn-results-success");
this.show_enrollment_list(data.result.EnrollmentList);
bio_enrollment_in_progress(false);
} else if (data.result.DeleteSuccess || data.result.AddSuccess) {
show_results_banner("success", "about-webauthn-results-success");
clear_bio_enrollment_samples();
// Update AuthenticatorInfo
this._curr_data = data.result.DeleteSuccess ?? data.result.AddSuccess;
fake_click_event_for_id("bio-enrollments-tab-button");
bio_enrollment_in_progress(false);
// If we still have some enrollments to show, update the list
// otherwise, remove it.
if (
this._curr_data.options.bioEnroll === true ||
this._curr_data.options.userVerificationMgmtPreview === true
) {
list_bio_enrollments();
} else {
// Hide the list, because it's empty
document.getElementById(
"bio-enrollment-list-subsection"
).hidden = true;
}
} else if (data.result.UpdateSuccess) {
fake_click_event_for_id("bio-enrollments-tab-button");
list_bio_enrollments();
} else if (data.result.SampleStatus) {
show_add_bio_enrollment_section();
let up = document.getElementById("enrollment-update");
let sample_update = document.createElement("div");
let new_line = document.createElement("label");
new_line.classList.add("sample");
new_line.setAttribute(
"data-l10n-id",
this._bio_l10n.get(data.result.SampleStatus[0])
);
sample_update.appendChild(new_line);
let samples_needed_line = document.createElement("label");
samples_needed_line.setAttribute(
"data-l10n-id",
"about-webauthn-samples-still-needed"
);
samples_needed_line.setAttribute(
"data-l10n-args",
JSON.stringify({ repeatCount: data.result.SampleStatus[1] })
);
sample_update.classList.add("bio-enrollment-sample");
sample_update.appendChild(samples_needed_line);
up.appendChild(sample_update);
}
} else if (data.type == "credential-management-update") {
credential_management_in_progress(false);
if (data.result.CredentialList) {
show_results_banner("success", "about-webauthn-results-success");
this.show_credential_list(data.result.CredentialList.credential_list);
} else {
// DeleteSuccess or UpdateSuccess
show_results_banner("success", "about-webauthn-results-success");
list_credentials();
}
} else if (data.type == "listen-success") {
reset_page();
// Show results
show_results_banner("success", "about-webauthn-results-success");
this._reset_in_progress = "";
AboutWebauthnService.listen();
} else if (data.type == "listen-error") {
reset_page();
if (!data.error) {
show_results_banner("error", "about-webauthn-results-general-error");
} else if (data.error.type == "pin-auth-blocked") {
show_results_banner(
"error",
"about-webauthn-results-pin-auth-blocked-error"
);
} else if (data.error.type == "pin-not-set") {
show_results_banner(
"error",
"about-webauthn-results-pin-not-set-error"
);
} else if (data.error.type == "device-blocked") {
show_results_banner(
"error",
"about-webauthn-results-pin-blocked-error"
);
} else if (data.error.type == "pin-is-too-short") {
show_results_banner(
"error",
"about-webauthn-results-pin-too-short-error"
);
} else if (data.error.type == "pin-is-too-long") {
show_results_banner(
"error",
"about-webauthn-results-pin-too-long-error"
);
} else if (data.error.type == "pin-invalid") {
let retries = data.error.retries
? JSON.stringify({ retriesLeft: data.error.retries })
: null;
show_results_banner(
"error",
"about-webauthn-results-pin-invalid-error",
retries
);
} else if (data.error.type == "cancel") {
show_results_banner(
"error",
"about-webauthn-results-cancelled-by-user-error"
);
} else {
show_results_banner("error", "about-webauthn-results-general-error");
}
AboutWebauthnService.listen();
}
},
show_authenticator_options(options, element, l10n_base) {
let table = document.getElementById(element);
var empty_table = document.createElement("table");
empty_table.id = element;
table.parentNode.replaceChild(empty_table, table);
table = document.getElementById(element);
for (let key in options) {
if (key == "options") {
continue;
}
// Create an empty
element and add it to the 1st position of the table:
var row = table.insertRow(0);
// Insert new cells ( elements) at the 1st and 2nd position of the "new" |
element:
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
// Add some text to the new cells:
let key_text = this._l10n.formatValueSync(
l10n_base + "-" + key.toLowerCase().replace(/_/g, "-")
);
var key_node = document.createTextNode(key_text);
cell1.appendChild(key_node);
var raw_value = JSON.stringify(options[key]);
var value = raw_value;
if (["true", "false", "null"].includes(raw_value)) {
value = this._l10n.formatValueSync(l10n_base + "-" + raw_value);
}
var value_node = document.createTextNode(value);
cell2.appendChild(value_node);
}
},
show_ui_based_on_authenticator_info(data) {
// Hide the "Please plug in a token"-message
document.getElementById("info-text-div").hidden = true;
// Show options, based on what the token supports
if (data.auth_info) {
document.getElementById("ctap2-token-info").style.display = "flex";
this.show_authenticator_options(
data.auth_info.options,
"authenticator-options",
"about-webauthn-auth-option"
);
this.show_authenticator_options(
data.auth_info,
"authenticator-info",
"about-webauthn-auth-info"
);
// Check if token supports PINs
if (data.auth_info.options.clientPin != null) {
document.getElementById("pin-tab-button").style.display = "flex";
if (data.auth_info.options.clientPin === true) {
// It has a Pin set
document.getElementById("change-pin-button").style.display = "block";
document.getElementById("set-pin-button").style.display = "none";
document.getElementById("current-pin-div").hidden = false;
} else {
// It does not have a Pin set yet
document.getElementById("change-pin-button").style.display = "none";
document.getElementById("set-pin-button").style.display = "block";
document.getElementById("current-pin-div").hidden = true;
}
} else {
document.getElementById("pin-tab-button").style.display = "none";
}
if (
data.auth_info.options.credMgmt ||
data.auth_info.options.credentialMgmtPreview
) {
document.getElementById("credentials-tab-button").style.display =
"flex";
} else {
document.getElementById("credentials-tab-button").style.display =
"none";
}
if (
data.auth_info.options.bioEnroll != null ||
data.auth_info.options.userVerificationMgmtPreview != null
) {
document.getElementById("bio-enrollments-tab-button").style.display =
"flex";
} else {
document.getElementById("bio-enrollments-tab-button").style.display =
"none";
}
} else {
// Currently auth-rs doesn't send this, because it filters out ctap2-devices.
// U2F / CTAP1 tokens can't be managed
set_info_text("about-webauthn-text-non-ctap2-device");
}
},
show_credential_list(credential_list) {
// We may have temporarily hidden the tab when asking the user for a PIN
// so we have to show it again.
fake_click_event_for_id("credentials-tab-button");
document.getElementById("credential-list-subsection").hidden = false;
let table = document.getElementById("credential-list");
var empty_table = document.createElement("table");
empty_table.id = "credential-list";
table.parentNode.replaceChild(empty_table, table);
if (!credential_list.length) {
document.getElementById("credential-list-empty-label").hidden = false;
return;
}
document.getElementById("credential-list-empty-label").hidden = true;
table = document.getElementById("credential-list");
credential_list.forEach(rp => {
// Add some text to the new cells:
let key_text = rp.rp.id;
rp.credentials.forEach(cred => {
let value_text = cred.user.name;
// Create an empty
element and add it to the 1st position of the table:
var row = table.insertRow(0);
var key_node = document.createTextNode(key_text);
var value_node = document.createTextNode(value_text);
row.insertCell(0).appendChild(key_node);
row.insertCell(1).appendChild(value_node);
var delete_button = document.createElement("button");
delete_button.classList.add("delete-button");
delete_button.classList.add("credentials-button");
let garbage_icon = document.createElement("img");
garbage_icon.setAttribute(
"src",
"chrome://global/skin/icons/delete.svg"
);
garbage_icon.classList.add("delete-icon");
delete_button.appendChild(garbage_icon);
let delete_text = document.createElement("span");
delete_text.setAttribute(
"data-l10n-id",
"about-webauthn-delete-button"
);
delete_button.appendChild(delete_text);
delete_button.addEventListener("click", function () {
let context = document.getElementById("confirmation-context");
context.textContent = key_text + " - " + value_text;
credential_management_in_progress(true);
let cmd = {
CredentialManagement: { DeleteCredential: cred.credential_id },
};
context.setAttribute("data-ctap-command", JSON.stringify(cmd));
open_delete_confirmation_tab();
});
row.insertCell(2).appendChild(delete_button);
});
});
},
show_enrollment_list(enrollment_list) {
// We may have temporarily hidden the tab when asking the user for a PIN
// so we have to show it again.
fake_click_event_for_id("bio-enrollments-tab-button");
document.getElementById("bio-enrollment-list-subsection").hidden = false;
let table = document.getElementById("bio-enrollment-list");
var empty_table = document.createElement("table");
empty_table.id = "bio-enrollment-list";
table.parentNode.replaceChild(empty_table, table);
if (!enrollment_list.length) {
document.getElementById("bio-enrollment-list-empty-label").hidden = false;
return;
}
document.getElementById("bio-enrollment-list-empty-label").hidden = true;
table = document.getElementById("bio-enrollment-list");
enrollment_list.forEach(enrollment => {
let key_text = enrollment.template_friendly_name ?? "";
var row = table.insertRow(0);
var key_node = document.createTextNode(key_text);
row.insertCell(0).appendChild(key_node);
var delete_button = document.createElement("button");
delete_button.classList.add("delete-button");
delete_button.classList.add("bio-enrollment-button");
let garbage_icon = document.createElement("img");
garbage_icon.setAttribute("src", "chrome://global/skin/icons/delete.svg");
garbage_icon.classList.add("delete-icon");
delete_button.appendChild(garbage_icon);
let delete_text = document.createElement("span");
delete_text.setAttribute("data-l10n-id", "about-webauthn-delete-button");
delete_button.appendChild(delete_text);
delete_button.addEventListener("click", function () {
let context = document.getElementById("confirmation-context");
context.textContent = key_text;
bio_enrollment_in_progress(true);
let cmd = {
BioEnrollment: { DeleteEnrollment: enrollment.template_id },
};
context.setAttribute("data-ctap-command", JSON.stringify(cmd));
open_delete_confirmation_tab();
});
row.insertCell(1).appendChild(delete_button);
});
},
};
function set_info_text(l10nId) {
document.getElementById("info-text-div").hidden = false;
let field = document.getElementById("info-text-field");
field.setAttribute("data-l10n-id", l10nId);
document.getElementById("ctap2-token-info").style.display = "none";
}
function show_results_banner(result, l10n, l10n_args) {
let ctap_result = document.getElementById("ctap-listen-result");
ctap_result.setAttribute("data-l10n-id", l10n);
ctap_result.classList.add(result);
if (l10n_args) {
ctap_result.setAttribute("data-l10n-args", l10n_args);
}
}
function hide_results_banner() {
let res_banner = document.getElementById("ctap-listen-result");
let res_div = document.getElementById("ctap-listen-div");
let empty_banner = document.createElement("label");
empty_banner.id = "ctap-listen-result";
res_div.replaceChild(empty_banner, res_banner);
}
function operation_in_progress(name, in_progress) {
let buttons = Array.from(document.getElementsByClassName(name));
buttons.forEach(button => {
button.disabled = in_progress;
});
}
function credential_management_in_progress(in_progress) {
operation_in_progress("credentials-button", in_progress);
}
function bio_enrollment_in_progress(in_progress) {
operation_in_progress("bio-enrollment-button", in_progress);
}
function clear_bio_enrollment_samples() {
// Remove all previous status updates
let up = document.getElementById("enrollment-update");
while (up.firstChild) {
up.removeChild(up.lastChild);
}
document.getElementById("enrollment-name").value = "";
}
function fake_click_event_for_id(id) {
// Not using document.getElementById(id).click();
// here, because we have to add additional data, so we don't
// hide the results-div here, if there is any. 'Normal' clicking
// by the user will hide it.
const evt = new CustomEvent("click", {
detail: { skip_results_clearing: true },
});
document.getElementById(id).dispatchEvent(evt);
}
function reset_page() {
// Hide everything that needs a device to know if it should be displayed
document.getElementById("ctap2-token-info").style.display = "none";
Array.from(document.getElementsByClassName("optional-category")).forEach(
div => {
div.style.display = "none";
}
);
// Only display the "please connect a device" - text
set_info_text("about-webauthn-text-connect-device");
// Clear results and input fields
hide_results_banner();
var divs = Array.from(document.getElementsByTagName("input"));
divs.forEach(div => {
div.value = "";
});
sidebar_set_disabled(false);
// ListCredentials
credential_management_in_progress(false);
document.getElementById("credential-list-subsection").hidden = true;
// BioEnrollment
clear_bio_enrollment_samples();
document.getElementById("bio-enrollment-list-subsection").hidden = true;
bio_enrollment_in_progress(false);
AboutWebauthnManagerJS._previous_tab = "";
AboutWebauthnManagerJS._current_tab = "";
// Not using `document.getElementById("info-tab-button").click();`
// here, because if we were focused on a category-button that got removed (e.g.
// when unplugging the device), we have to reset the ARIA-related attributes
// first, before we can click on the button, otherwise the a11y-tests
// will complain. So we fake the click again.
const evt = {
detail: {},
currentTarget: document.getElementById("info-tab-button"),
};
open_info_tab(evt);
}
function sidebar_set_disabled(disabled) {
var cats = Array.from(document.getElementsByClassName("category"));
cats.forEach(cat => {
if (disabled) {
cat.classList.add("disabled-category");
} else {
cat.classList.remove("disabled-category");
}
});
}
function check_pin_repeat_is_correct(button) {
let pin = document.getElementById("new-pin");
let pin_repeat = document.getElementById("new-pin-repeat");
let has_current_pin = !document.getElementById("current-pin-div").hidden;
let current_pin = document.getElementById("current-pin");
let can_enable_button =
pin.value != null && pin.value != "" && pin.value == pin_repeat.value;
if (has_current_pin && !current_pin.value) {
can_enable_button = false;
}
if (!can_enable_button) {
pin.classList.add("different");
pin_repeat.classList.add("different");
document.getElementById("set-pin-button").disabled = true;
document.getElementById("change-pin-button").disabled = true;
return false;
}
pin.classList.remove("different");
pin_repeat.classList.remove("different");
document.getElementById("set-pin-button").disabled = false;
document.getElementById("change-pin-button").disabled = false;
return true;
}
function send_pin() {
close_temporary_overlay_tab();
let pin = document.getElementById("pin-required").value;
AboutWebauthnService.pinCallback(0, pin);
}
function set_pin() {
let pin = document.getElementById("new-pin").value;
let cmd = { SetPIN: pin };
AboutWebauthnService.runCommand(JSON.stringify(cmd));
}
function change_pin() {
let curr_pin = document.getElementById("current-pin").value;
let new_pin = document.getElementById("new-pin").value;
let cmd = { ChangePIN: [curr_pin, new_pin] };
AboutWebauthnService.runCommand(JSON.stringify(cmd));
}
function list_credentials() {
credential_management_in_progress(true);
let cmd = { CredentialManagement: "GetCredentials" };
AboutWebauthnService.runCommand(JSON.stringify(cmd));
}
function list_bio_enrollments() {
bio_enrollment_in_progress(true);
let cmd = { BioEnrollment: "GetEnrollments" };
AboutWebauthnService.runCommand(JSON.stringify(cmd));
}
function show_add_bio_enrollment_section() {
const evt = new CustomEvent("click", {
detail: { temporary_overlay: true },
});
open_tab(evt, "add-bio-enrollment-section");
document.getElementById("enrollment-name").focus();
}
function start_bio_enrollment() {
bio_enrollment_in_progress(true);
let name = document.getElementById("enrollment-name").value;
if (!name) {
name = null; // Empty means "Not set"
}
let cmd = { BioEnrollment: { StartNewEnrollment: name } };
AboutWebauthnService.runCommand(JSON.stringify(cmd));
}
function cancel_transaction() {
credential_management_in_progress(false);
bio_enrollment_in_progress(false);
AboutWebauthnService.cancel(0);
}
function confirm_deletion() {
let context = document.getElementById("confirmation-context");
let cmd = context.getAttribute("data-ctap-command");
AboutWebauthnService.runCommand(cmd);
}
function cancel_confirmation() {
credential_management_in_progress(false);
bio_enrollment_in_progress(false);
close_temporary_overlay_tab();
}
async function onLoad() {
document.getElementById("set-pin-button").addEventListener("click", set_pin);
document
.getElementById("change-pin-button")
.addEventListener("click", change_pin);
document
.getElementById("list-credentials-button")
.addEventListener("click", list_credentials);
document
.getElementById("list-bio-enrollments-button")
.addEventListener("click", list_bio_enrollments);
document
.getElementById("add-bio-enrollment-button")
.addEventListener("click", show_add_bio_enrollment_section);
document
.getElementById("start-enrollment-button")
.addEventListener("click", start_bio_enrollment);
document
.getElementById("new-pin")
.addEventListener("input", check_pin_repeat_is_correct);
document
.getElementById("new-pin-repeat")
.addEventListener("input", check_pin_repeat_is_correct);
document
.getElementById("current-pin")
.addEventListener("input", check_pin_repeat_is_correct);
let info_button = document.getElementById("info-tab-button");
info_button.addEventListener("click", open_info_tab);
info_button.addEventListener("keydown", handle_keydowns);
let pin_button = document.getElementById("pin-tab-button");
pin_button.addEventListener("click", open_pin_tab);
pin_button.addEventListener("keydown", handle_keydowns);
let credentials_button = document.getElementById("credentials-tab-button");
credentials_button.addEventListener("click", open_credentials_tab);
credentials_button.addEventListener("keydown", handle_keydowns);
let bio_enrollments_button = document.getElementById(
"bio-enrollments-tab-button"
);
bio_enrollments_button.addEventListener("click", open_bio_enrollments_tab);
bio_enrollments_button.addEventListener("keydown", handle_keydowns);
document
.getElementById("send-pin-button")
.addEventListener("click", send_pin);
document
.getElementById("cancel-send-pin-button")
.addEventListener("click", cancel_transaction);
document
.getElementById("cancel-enrollment-button")
.addEventListener("click", cancel_transaction);
document
.getElementById("cancel-confirmation-button")
.addEventListener("click", cancel_confirmation);
document
.getElementById("confirm-deletion-button")
.addEventListener("click", confirm_deletion);
AboutWebauthnManagerJS.init();
try {
AboutWebauthnService.listen();
} catch (ex) {
set_info_text("about-webauthn-text-not-available");
AboutWebauthnManagerJS.uninit();
}
}
function handle_keydowns(event) {
let index;
let event_was_handled = true;
let tabs = Array.from(document.getElementsByClassName("category"));
if (tabs.length <= 0) {
return;
}
switch (event.key) {
case "ArrowLeft":
case "ArrowUp":
if (event.currentTarget === tabs[0]) {
event.currentTarget.focus();
} else {
index = tabs.indexOf(event.currentTarget);
tabs[index - 1].focus();
}
break;
case "ArrowRight":
case "ArrowDown":
if (event.currentTarget === tabs[tabs.length - 1]) {
event.currentTarget.focus();
} else {
index = tabs.indexOf(event.currentTarget);
tabs[index + 1].focus();
}
break;
case "Home":
tabs[0].focus();
break;
case "End":
tabs[tabs.length - 1].focus();
break;
case "Enter":
case " ":
event.currentTarget.click();
break;
default:
event_was_handled = false;
break;
}
if (event_was_handled) {
event.stopPropagation();
event.preventDefault();
}
}
function open_tab(evt, tabName) {
var tabcontent, tablinks;
// Hide all others
tabcontent = Array.from(document.getElementsByClassName("tabcontent"));
tabcontent.forEach(tab => {
tab.style.display = "none";
});
// Display the one we selected
document.getElementById(tabName).style.display = "block";
// If this is a temporary overlay, like pin-required, we don't
// touch the sidebar and which button is selected.
if (!evt.detail.temporary_overlay) {
tablinks = Array.from(document.getElementsByClassName("category"));
tablinks.forEach(tablink => {
tablink.removeAttribute("selected");
tablink.setAttribute("aria-selected", "false");
tablink.setAttribute("tabindex", "-1");
tablink.disabled = false;
});
evt.currentTarget.setAttribute("selected", "true");
evt.currentTarget.setAttribute("tabindex", "0");
evt.currentTarget.setAttribute("aria-selected", "true");
}
if (!evt.detail.skip_results_clearing) {
hide_results_banner();
}
sidebar_set_disabled(false);
AboutWebauthnManagerJS._previous_tab = AboutWebauthnManagerJS._current_tab;
AboutWebauthnManagerJS._current_tab = tabName;
}
function open_info_tab(evt) {
open_tab(evt, "token-info-section");
}
function open_pin_tab(evt) {
open_tab(evt, "set-change-pin-section");
}
function open_credentials_tab(evt) {
open_tab(evt, "credential-management-section");
}
function open_bio_enrollments_tab(evt) {
// We can only list, if there are any registered already
if (
AboutWebauthnManagerJS._curr_data.options.bioEnroll === true ||
AboutWebauthnManagerJS._curr_data.options.userVerificationMgmtPreview ===
true
) {
document.getElementById("list-bio-enrollments-button").style.display =
"inline-block";
} else {
document.getElementById("list-bio-enrollments-button").style.display =
"none";
}
open_tab(evt, "bio-enrollment-section");
}
function open_reset_tab(evt) {
open_tab(evt, "reset-token-section");
}
function open_pin_required_tab() {
// Remove any old value we might have had
document.getElementById("pin-required").value = "";
const evt = new CustomEvent("click", {
detail: {
temporary_overlay: true,
skip_results_clearing: true, // We might be called multiple times, if PIN was invalid
},
});
open_tab(evt, "pin-required-section");
document.getElementById("pin-required").focus();
// This is a temporary overlay, so we don't want the
// user to click away from it, unless via the Cancel-button.
sidebar_set_disabled(true);
}
function close_temporary_overlay_tab() {
const evt = new CustomEvent("click", {
detail: { temporary_overlay: true },
});
open_tab(evt, AboutWebauthnManagerJS._previous_tab);
sidebar_set_disabled(false);
}
function open_delete_confirmation_tab() {
const evt = new CustomEvent("click", {
detail: {
temporary_overlay: true,
},
});
open_tab(evt, "confirm-deletion-section");
// This is a temporary overlay, so we don't want the
// user to click away from it, unless via the Cancel-button.
sidebar_set_disabled(true);
}
try {
AboutWebauthnService = Cc["@mozilla.org/webauthn/service;1"].getService(
Ci.nsIWebAuthnService
);
document.addEventListener("DOMContentLoaded", onLoad);
window.addEventListener("beforeunload", event => {
AboutWebauthnManagerJS.uninit();
if (AboutWebauthnService) {
AboutWebauthnService.cancel(0);
}
});
} catch (ex) {
// Do nothing if we fail to create a singleton instance,
// showing the default no-module message.
console.error(ex);
}