Bug 1938475 [Wayland] Fallback to monitor screen scale if we're missing wayland surfa...
[gecko.git] / security / manager / ssl / tests / mochitest / browser / browser_clientAuthRememberService.js
blob87b476e012681e57bd8b64d102ea0ae4d89a8e10
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 /**
7  * Test certificate (i.e. build/pgo/certs/mochitest.client).
8  *
9  * @type {nsIX509Cert}
10  */
11 var cert;
12 var cert2;
13 var cert3;
15 var sdr = Cc["@mozilla.org/security/sdr;1"].getService(Ci.nsISecretDecoderRing);
16 var certDB = Cc["@mozilla.org/security/x509certdb;1"].getService(
17   Ci.nsIX509CertDB
20 var deleted = false;
22 const { MockRegistrar } = ChromeUtils.importESModule(
23   "resource://testing-common/MockRegistrar.sys.mjs"
26 function findCertByCommonName(commonName) {
27   for (let cert of certDB.getCerts()) {
28     if (cert.commonName == commonName) {
29       return cert;
30     }
31   }
32   return null;
35 async function testHelper(connectURL, expectedURL) {
36   let win = await BrowserTestUtils.openNewBrowserWindow();
38   await SpecialPowers.pushPrefEnv({
39     set: [["security.default_personal_cert", "Ask Every Time"]],
40   });
42   BrowserTestUtils.startLoadingURIString(
43     win.gBrowser.selectedBrowser,
44     connectURL
45   );
47   await BrowserTestUtils.browserLoaded(
48     win.gBrowser.selectedBrowser,
49     false,
50     expectedURL,
51     true
52   );
53   let loadedURL = win.gBrowser.selectedBrowser.documentURI.spec;
54   Assert.ok(
55     loadedURL.startsWith(expectedURL),
56     `Expected and actual URLs should match (got '${loadedURL}', expected '${expectedURL}')`
57   );
59   await win.close();
61   // This clears the TLS session cache so we don't use a previously-established
62   // ticket to connect and bypass selecting a client auth certificate in
63   // subsequent tests.
64   sdr.logout();
67 async function openRequireClientCert() {
68   gClientAuthDialogService.chooseCertificateCalled = false;
69   await testHelper(
70     "https://requireclientcert.example.com:443",
71     "https://requireclientcert.example.com/"
72   );
75 async function openRequireClientCert2() {
76   gClientAuthDialogService.chooseCertificateCalled = false;
77   await testHelper(
78     "https://requireclientcert-2.example.com:443",
79     "https://requireclientcert-2.example.com/"
80   );
83 // Mock implementation of nsIClientAuthRememberService
84 const gClientAuthRememberService = {
85   forgetRememberedDecision(key) {
86     deleted = true;
87     Assert.equal(
88       key,
89       "exampleKey2",
90       "Expected to get the same key that was passed in getDecisions()"
91     );
92   },
94   getDecisions() {
95     return [
96       {
97         asciiHost: "example.com",
98         dbKey: cert.dbKey,
99         entryKey: "exampleKey1",
100       },
101       {
102         asciiHost: "example.org",
103         dbKey: cert2.dbKey,
104         entryKey: "exampleKey2",
105       },
106       {
107         asciiHost: "example.test",
108         dbKey: cert3.dbKey,
109         entryKey: "exampleKey3",
110       },
111       {
112         asciiHost: "unavailable.example.com",
113         // This dbKey should not correspond to any real certificate. The first
114         // 8 bytes have to be 0, followed by the lengths of the serial number
115         // and issuer distinguished name, respectively, and then followed by
116         // the bytes of the serial number and finally the encoded issuer
117         // distinguished name. In this case, the serial number is a single 0
118         // byte and the issuer distinguished name is a DER SEQUENCE of length 0
119         // (the bytes 0x30 and 0).
120         // See also the documentation in nsNSSCertificateDB::FindCertByDBKey.
121         dbKey: "AAAAAAAAAAAAAAABAAAAAgAeAA==",
122         entryKey: "exampleKey4",
123       },
124     ];
125   },
127   QueryInterface: ChromeUtils.generateQI(["nsIClientAuthRememberService"]),
130 const gClientAuthDialogService = {
131   _chooseCertificateCalled: false,
133   get chooseCertificateCalled() {
134     return this._chooseCertificateCalled;
135   },
137   set chooseCertificateCalled(value) {
138     this._chooseCertificateCalled = value;
139   },
141   chooseCertificate(hostname, certArray, loadContext, callback) {
142     this.chooseCertificateCalled = true;
143     callback.certificateChosen(certArray[0], true);
144   },
146   QueryInterface: ChromeUtils.generateQI([Ci.nsIClientAuthDialogService]),
149 add_task(async function testRememberedDecisionsUI() {
150   cert = findCertByCommonName("Mochitest client");
151   cert2 = await readCertificate("pgo-ca-all-usages.pem", ",,");
152   cert3 = await readCertificate("client-cert-via-intermediate.pem", ",,");
153   isnot(cert, null, "Should be able to find the test client cert");
154   isnot(cert2, null, "Should be able to find pgo-ca-all-usages.pem");
155   isnot(cert3, null, "Should be able to find client-cert-via-intermediate.pem");
157   let clientAuthRememberServiceCID = MockRegistrar.register(
158     "@mozilla.org/security/clientAuthRememberService;1",
159     gClientAuthRememberService
160   );
162   let win = await openCertManager();
164   let listItems = win.document
165     .getElementById("rememberedList")
166     .querySelectorAll("richlistitem");
168   Assert.equal(
169     listItems.length,
170     4,
171     "rememberedList has expected number of items"
172   );
174   let labels = win.document
175     .getElementById("rememberedList")
176     .querySelectorAll("label");
178   Assert.equal(
179     labels.length,
180     12,
181     "rememberedList has expected number of labels"
182   );
184   await BrowserTestUtils.waitForCondition(
185     () => !!labels[10].textContent.length,
186     "Localized label is populated"
187   );
189   let expectedHosts = [
190     "example.com",
191     "example.org",
192     "example.test",
193     "unavailable.example.com",
194   ];
195   let hosts = [
196     labels[0].value,
197     labels[3].value,
198     labels[6].value,
199     labels[9].value,
200   ];
201   let expectedNames = [
202     cert.commonName,
203     cert2.commonName,
204     cert3.commonName,
205     "(Unavailable)",
206   ];
207   let names = [
208     labels[1].value,
209     labels[4].value,
210     labels[7].value,
211     labels[10].textContent,
212   ];
213   let expectedSerialNumbers = [
214     cert.serialNumber,
215     cert2.serialNumber,
216     cert3.serialNumber,
217     "(Unavailable)",
218   ];
219   let serialNumbers = [
220     labels[2].value,
221     labels[5].value,
222     labels[8].value,
223     labels[11].textContent,
224   ];
226   for (let i = 0; i < listItems.length; i++) {
227     Assert.equal(hosts[i], expectedHosts[i], "got expected asciiHost");
228     Assert.equal(names[i], expectedNames[i], "got expected commonName");
229     Assert.equal(
230       serialNumbers[i],
231       expectedSerialNumbers[i],
232       "got expected serialNumber"
233     );
234   }
236   win.document.getElementById("rememberedList").selectedIndex = 1;
237   win.document.getElementById("remembered_deleteButton").click();
239   Assert.ok(deleted, "Expected forgetRememberedDecision() to get called");
241   win.document.getElementById("certmanager").acceptDialog();
242   await BrowserTestUtils.windowClosed(win);
244   MockRegistrar.unregister(clientAuthRememberServiceCID);
247 add_task(async function testDeletingRememberedDecisions() {
248   let clientAuthDialogServiceCID = MockRegistrar.register(
249     "@mozilla.org/security/ClientAuthDialogService;1",
250     gClientAuthDialogService
251   );
252   let cars = Cc["@mozilla.org/security/clientAuthRememberService;1"].getService(
253     Ci.nsIClientAuthRememberService
254   );
256   await openRequireClientCert();
257   Assert.ok(
258     gClientAuthDialogService.chooseCertificateCalled,
259     "chooseCertificate should have been called if visiting 'requireclientcert.example.com' for the first time"
260   );
262   await openRequireClientCert();
263   Assert.ok(
264     !gClientAuthDialogService.chooseCertificateCalled,
265     "chooseCertificate should not have been called if visiting 'requireclientcert.example.com' for the second time"
266   );
268   await openRequireClientCert2();
269   Assert.ok(
270     gClientAuthDialogService.chooseCertificateCalled,
271     "chooseCertificate should have been called if visiting 'requireclientcert-2.example.com' for the first time"
272   );
274   let originAttributes = { privateBrowsingId: 0 };
275   cars.deleteDecisionsByHost("requireclientcert.example.com", originAttributes);
277   await openRequireClientCert();
278   Assert.ok(
279     gClientAuthDialogService.chooseCertificateCalled,
280     "chooseCertificate should have been called after removing all remembered decisions for 'requireclientcert.example.com'"
281   );
283   await openRequireClientCert2();
284   Assert.ok(
285     !gClientAuthDialogService.chooseCertificateCalled,
286     "chooseCertificate should not have been called if visiting 'requireclientcert-2.example.com' for the second time"
287   );
289   MockRegistrar.unregister(clientAuthDialogServiceCID);