1 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
2 // Any copyright is dedicated to the Public Domain.
3 // http://creativecommons.org/publicdomain/zero/1.0/
6 // Tests that the client authentication certificate chooser correctly displays
7 // provided information and correctly returns user input.
9 const TEST_HOSTNAME = "Test Hostname";
10 const TEST_ORG = "Test Org";
11 const TEST_ISSUER_ORG = "Test Issuer Org";
12 const TEST_PORT = 123;
14 var certDB = Cc["@mozilla.org/security/x509certdb;1"].getService(
18 ChromeUtils.defineESModuleGetters(this, {
19 PromptUtils: "resource://gre/modules/PromptUtils.sys.mjs",
23 * Test certificate (i.e. build/pgo/certs/mochitest.client).
30 * Opens the client auth cert chooser dialog.
32 * @param {nsIX509Cert} cert The cert to pass to the dialog for display.
34 * A promise that resolves when the dialog has finished loading, with
35 * an array consisting of:
36 * 1. The window of the opened dialog.
37 * 2. The return value nsIWritablePropertyBag2 passed to the dialog.
39 function openClientAuthDialog(cert) {
40 let certArray = [cert];
41 let retVals = { cert: undefined, rememberDecision: undefined };
42 let args = PromptUtils.objectToPropBag({
43 hostname: TEST_HOSTNAME,
47 let win = window.openDialog(
48 "chrome://pippki/content/clientauthask.xhtml",
53 return TestUtils.topicObserved("cert-dialog-loaded").then(() => {
54 return { win, retVals };
59 * Checks that the contents of the given cert chooser dialog match the details
60 * of build/pgo/certs/mochitest.client.
62 * @param {window} win The cert chooser window.
63 * @param {string} notBefore
64 * The formatted notBefore date of mochitest.client.
65 * @param {string} notAfter
66 * The formatted notAfter date of mochitest.client.
68 async function checkDialogContents(win, notBefore, notAfter) {
69 await TestUtils.waitForCondition(() => {
71 .getElementById("clientAuthSiteIdentification")
72 .textContent.includes(`${TEST_HOSTNAME}`);
74 let nicknames = win.document.getElementById("nicknames");
75 await TestUtils.waitForCondition(() => {
76 return nicknames.label == "Mochitest client [03]";
78 await TestUtils.waitForCondition(() => {
79 return nicknames.itemCount == 1;
81 let subject = win.document.getElementById("clientAuthCertDetailsIssuedTo");
82 await TestUtils.waitForCondition(() => {
83 return subject.textContent == "Issued to: CN=Mochitest client";
85 let serialNum = win.document.getElementById(
86 "clientAuthCertDetailsSerialNumber"
88 await TestUtils.waitForCondition(() => {
89 return serialNum.textContent == "Serial number: 03";
91 let validity = win.document.getElementById(
92 "clientAuthCertDetailsValidityPeriod"
94 await TestUtils.waitForCondition(() => {
95 return validity.textContent == `Valid from ${notBefore} to ${notAfter}`;
97 let issuer = win.document.getElementById("clientAuthCertDetailsIssuedBy");
98 await TestUtils.waitForCondition(() => {
100 issuer.textContent ==
101 "Issued by: OU=Profile Guided Optimization,O=Mozilla Testing,CN=Temporary Certificate Authority"
104 let tokenName = win.document.getElementById("clientAuthCertDetailsStoredOn");
105 await TestUtils.waitForCondition(() => {
106 return tokenName.textContent == "Stored on: Software Security Device";
110 function findCertByCommonName(commonName) {
111 for (let cert of certDB.getCerts()) {
112 if (cert.commonName == commonName) {
119 add_setup(async function () {
120 cert = findCertByCommonName("Mochitest client");
121 isnot(cert, null, "Should be able to find the test client cert");
124 // Test that the contents of the dialog correspond to the details of the
126 add_task(async function testContents() {
127 const formatter = new Intl.DateTimeFormat(undefined, {
131 let { win } = await openClientAuthDialog(cert);
132 await checkDialogContents(
134 formatter.format(new Date(cert.validity.notBefore / 1000)),
135 formatter.format(new Date(cert.validity.notAfter / 1000))
137 await BrowserTestUtils.closeWindow(win);
140 // Test that the right values are returned when the dialog is accepted.
141 add_task(async function testAcceptDialogReturnValues() {
142 let { win, retVals } = await openClientAuthDialog(cert);
143 win.document.getElementById("rememberBox").checked = true;
144 info("Accepting dialog");
145 win.document.getElementById("certAuthAsk").acceptDialog();
146 await BrowserTestUtils.windowClosed(win);
148 is(retVals.cert, cert, "cert should be returned as chosen cert");
150 retVals.rememberDecision,
151 "Return value should signal 'Remember this decision' checkbox was checked"
155 // Test that the right values are returned when the dialog is canceled.
156 add_task(async function testCancelDialogReturnValues() {
157 let { win, retVals } = await openClientAuthDialog(cert);
158 win.document.getElementById("rememberBox").checked = false;
159 info("Canceling dialog");
160 win.document.getElementById("certAuthAsk").cancelDialog();
161 await BrowserTestUtils.windowClosed(win);
165 "Return value should signal user did not choose a certificate"
168 !retVals.rememberDecision,
169 "Return value should signal 'Remember this decision' checkbox was unchecked"