Bug 1917491 - Part 3: Introduce call-like syntax for resource disposal in DisposableS...
[gecko.git] / security / manager / ssl / tests / mochitest / browser / browser_clientAuth_ui.js
blob2e9ff0557e340a557e09dea425324fa0aeccd8cb
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/
4 "use strict";
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(
15   Ci.nsIX509CertDB
18 ChromeUtils.defineESModuleGetters(this, {
19   PromptUtils: "resource://gre/modules/PromptUtils.sys.mjs",
20 });
22 /**
23  * Test certificate (i.e. build/pgo/certs/mochitest.client).
24  *
25  * @type {nsIX509Cert}
26  */
27 var cert;
29 /**
30  * Opens the client auth cert chooser dialog.
31  *
32  * @param {nsIX509Cert} cert The cert to pass to the dialog for display.
33  * @returns {Promise}
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.
38  */
39 function openClientAuthDialog(cert) {
40   let certArray = [cert];
41   let retVals = { cert: undefined, rememberDecision: undefined };
42   let args = PromptUtils.objectToPropBag({
43     hostname: TEST_HOSTNAME,
44     certArray,
45     retVals,
46   });
47   let win = window.openDialog(
48     "chrome://pippki/content/clientauthask.xhtml",
49     "",
50     "",
51     args
52   );
53   return TestUtils.topicObserved("cert-dialog-loaded").then(() => {
54     return { win, retVals };
55   });
58 /**
59  * Checks that the contents of the given cert chooser dialog match the details
60  * of build/pgo/certs/mochitest.client.
61  *
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.
67  */
68 async function checkDialogContents(win, notBefore, notAfter) {
69   await TestUtils.waitForCondition(() => {
70     return win.document
71       .getElementById("clientAuthSiteIdentification")
72       .textContent.includes(`${TEST_HOSTNAME}`);
73   });
74   let nicknames = win.document.getElementById("nicknames");
75   await TestUtils.waitForCondition(() => {
76     return nicknames.label == "Mochitest client [03]";
77   });
78   await TestUtils.waitForCondition(() => {
79     return nicknames.itemCount == 1;
80   });
81   let subject = win.document.getElementById("clientAuthCertDetailsIssuedTo");
82   await TestUtils.waitForCondition(() => {
83     return subject.textContent == "Issued to: CN=Mochitest client";
84   });
85   let serialNum = win.document.getElementById(
86     "clientAuthCertDetailsSerialNumber"
87   );
88   await TestUtils.waitForCondition(() => {
89     return serialNum.textContent == "Serial number: 03";
90   });
91   let validity = win.document.getElementById(
92     "clientAuthCertDetailsValidityPeriod"
93   );
94   await TestUtils.waitForCondition(() => {
95     return validity.textContent == `Valid from ${notBefore} to ${notAfter}`;
96   });
97   let issuer = win.document.getElementById("clientAuthCertDetailsIssuedBy");
98   await TestUtils.waitForCondition(() => {
99     return (
100       issuer.textContent ==
101       "Issued by: OU=Profile Guided Optimization,O=Mozilla Testing,CN=Temporary Certificate Authority"
102     );
103   });
104   let tokenName = win.document.getElementById("clientAuthCertDetailsStoredOn");
105   await TestUtils.waitForCondition(() => {
106     return tokenName.textContent == "Stored on: Software Security Device";
107   });
110 function findCertByCommonName(commonName) {
111   for (let cert of certDB.getCerts()) {
112     if (cert.commonName == commonName) {
113       return cert;
114     }
115   }
116   return null;
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
125 // provided cert.
126 add_task(async function testContents() {
127   const formatter = new Intl.DateTimeFormat(undefined, {
128     dateStyle: "medium",
129     timeStyle: "long",
130   });
131   let { win } = await openClientAuthDialog(cert);
132   await checkDialogContents(
133     win,
134     formatter.format(new Date(cert.validity.notBefore / 1000)),
135     formatter.format(new Date(cert.validity.notAfter / 1000))
136   );
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");
149   ok(
150     retVals.rememberDecision,
151     "Return value should signal 'Remember this decision' checkbox was checked"
152   );
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);
163   ok(
164     !retVals.cert,
165     "Return value should signal user did not choose a certificate"
166   );
167   ok(
168     !retVals.rememberDecision,
169     "Return value should signal 'Remember this decision' checkbox was unchecked"
170   );