browser_deleteCert_ui.js (7798B)
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"; 5 6 // Tests various aspects of the cert delete confirmation dialog. 7 // Among other things, tests that for each type of cert that can be deleted: 8 // 1. The various lines of explanation text are correctly set. 9 // 2. The implementation correctly falls back through multiple cert attributes 10 // to determine what to display to represent a cert. 11 12 /** 13 * An array of tree items corresponding to TEST_CASES. 14 * 15 * @type {nsICertTreeItem[]} 16 */ 17 var gCertArray = []; 18 19 const FAKE_HOST_PORT = "Fake host and port"; 20 21 /** 22 * @typedef TestCase 23 * @type {object} 24 * @property {string} certFilename 25 * Filename of the cert, or null if we don't want to import a cert for 26 * this test case (i.e. we expect the hostPort attribute of 27 * nsICertTreeItem to be used). 28 * @property {string} expectedDisplayString 29 * The string we expect the UI to display to represent the given cert. 30 * @property {string} expectedSerialNumber 31 * The serial number we expect the UI to display if it exists. 32 */ 33 34 /** 35 * A list of test cases representing certs that get "deleted". 36 * 37 * @type {TestCase[]} 38 */ 39 const TEST_CASES = [ 40 { 41 certFilename: null, 42 expectedDisplayString: FAKE_HOST_PORT, 43 expectedSerialNumber: null, 44 }, 45 { 46 certFilename: "has-cn.pem", 47 expectedDisplayString: "Foo", 48 expectedSerialNumber: null, 49 }, 50 { 51 certFilename: "has-ou.pem", 52 expectedDisplayString: "Bar", 53 expectedSerialNumber: null, 54 }, 55 { 56 certFilename: "has-o.pem", 57 expectedDisplayString: "Baz", 58 expectedSerialNumber: null, 59 }, 60 { 61 certFilename: "has-non-empty-subject.pem", 62 expectedDisplayString: "C=US", 63 expectedSerialNumber: null, 64 }, 65 { 66 certFilename: "has-empty-subject.pem", 67 expectedDisplayString: "Certificate with serial number: 0A", 68 expectedSerialNumber: "0A", 69 }, 70 ]; 71 72 /** 73 * Opens the cert delete confirmation dialog. 74 * 75 * @param {string} tabID 76 * The ID of the cert category tab the certs to delete belong to. 77 * @returns {Promise} 78 * A promise that resolves when the dialog has finished loading, with 79 * an array consisting of: 80 * 1. The window of the opened dialog. 81 * 2. The return value object passed to the dialog. 82 */ 83 function openDeleteCertConfirmDialog(tabID) { 84 let retVals = { 85 deleteConfirmed: false, 86 }; 87 let win = window.openDialog( 88 "chrome://pippki/content/deletecert.xhtml", 89 "", 90 "", 91 tabID, 92 gCertArray, 93 retVals 94 ); 95 return new Promise(resolve => { 96 win.addEventListener( 97 "load", 98 function () { 99 executeSoon(() => resolve([win, retVals])); 100 }, 101 { once: true } 102 ); 103 }); 104 } 105 106 add_setup(async function () { 107 for (let testCase of TEST_CASES) { 108 let cert = null; 109 if (testCase.certFilename) { 110 cert = await readCertificate(testCase.certFilename, ",,"); 111 } 112 let certTreeItem = { 113 hostPort: FAKE_HOST_PORT, 114 cert, 115 QueryInterface: ChromeUtils.generateQI(["nsICertTreeItem"]), 116 }; 117 gCertArray.push(certTreeItem); 118 } 119 }); 120 121 /** 122 * Test helper for the below test cases. 123 * 124 * @param {string} tabID 125 * ID of the cert category tab the certs to delete belong to. 126 * @param {string} expectedTitleL10nId 127 * The L10nId of title the dialog is expected to have. 128 * @param {string} expectedConfirmL10nId 129 * The l10n id of confirmation message the dialog expected to show. 130 * @param {string} expectedImpactL10nId 131 * The l10n id of impact the dialog expected to show. 132 */ 133 async function testHelper( 134 tabID, 135 expectedTitleL10nId, 136 expectedConfirmL10nId, 137 expectedImpactL10nId 138 ) { 139 let [win] = await openDeleteCertConfirmDialog(tabID); 140 let certList = win.document.getElementById("certlist"); 141 142 Assert.deepEqual( 143 win.document.l10n.getAttributes(win.document.documentElement), 144 expectedTitleL10nId, 145 `Actual and expected titles should match for ${tabID}` 146 ); 147 let confirm = win.document.getElementById("confirm"); 148 Assert.deepEqual( 149 win.document.l10n.getAttributes(confirm), 150 expectedConfirmL10nId, 151 `Actual and expected confirm message should match for ${tabID}` 152 ); 153 let impact = win.document.getElementById("impact"); 154 Assert.deepEqual( 155 win.document.l10n.getAttributes(impact), 156 expectedImpactL10nId, 157 `Actual and expected impact should match for ${tabID}` 158 ); 159 160 Assert.equal( 161 certList.itemCount, 162 TEST_CASES.length, 163 `No. of certs displayed should match for ${tabID}` 164 ); 165 for (let i = 0; i < certList.itemCount; i++) { 166 let item = certList.getItemAtIndex(i); 167 if (TEST_CASES[i].expectedSerialNumber == null) { 168 Assert.equal( 169 item.label, 170 TEST_CASES[i].expectedDisplayString, 171 "Actual and expected display string should match for " + 172 `index ${i} for ${tabID}` 173 ); 174 } else { 175 Assert.deepEqual( 176 win.document.l10n.getAttributes(item.children[0]), 177 { 178 id: "cert-with-serial", 179 args: { serialNumber: TEST_CASES[i].expectedSerialNumber }, 180 }, 181 "Actual and expected display string should match for " + 182 `index ${i} for ${tabID}` 183 ); 184 } 185 } 186 187 await BrowserTestUtils.closeWindow(win); 188 } 189 190 // Test deleting certs from the "Your Certificates" tab. 191 add_task(async function testDeletePersonalCerts() { 192 const expectedTitleL10nId = { id: "delete-user-cert-title", args: null }; 193 const expectedConfirmL10nId = { id: "delete-user-cert-confirm", args: null }; 194 const expectedImpactL10nId = { id: "delete-user-cert-impact", args: null }; 195 await testHelper( 196 "mine_tab", 197 expectedTitleL10nId, 198 expectedConfirmL10nId, 199 expectedImpactL10nId 200 ); 201 }); 202 203 // Test deleting certs from the "People" tab. 204 add_task(async function testDeleteOtherPeopleCerts() { 205 const expectedTitleL10nId = { id: "delete-email-cert-title", args: null }; 206 // ’ doesn't seem to work when embedded in the following literals, which is 207 // why escape codes are used instead. 208 const expectedConfirmL10nId = { id: "delete-email-cert-confirm", args: null }; 209 const expectedImpactL10nId = { id: "delete-email-cert-impact", args: null }; 210 await testHelper( 211 "others_tab", 212 expectedTitleL10nId, 213 expectedConfirmL10nId, 214 expectedImpactL10nId 215 ); 216 }); 217 218 // Test deleting certs from the "Authorities" tab. 219 add_task(async function testDeleteCACerts() { 220 const expectedTitleL10nId = { id: "delete-ca-cert-title", args: null }; 221 const expectedConfirmL10nId = { id: "delete-ca-cert-confirm", args: null }; 222 const expectedImpactL10nId = { id: "delete-ca-cert-impact", args: null }; 223 await testHelper( 224 "ca_tab", 225 expectedTitleL10nId, 226 expectedConfirmL10nId, 227 expectedImpactL10nId 228 ); 229 }); 230 231 // Test that the right values are returned when the dialog is accepted. 232 add_task(async function testAcceptDialogReturnValues() { 233 let [win, retVals] = await openDeleteCertConfirmDialog( 234 "ca_tab" /* arbitrary */ 235 ); 236 info("Accepting dialog"); 237 win.document.getElementById("deleteCertificate").acceptDialog(); 238 await BrowserTestUtils.windowClosed(win); 239 240 Assert.ok( 241 retVals.deleteConfirmed, 242 "Return value should signal user accepted" 243 ); 244 }); 245 246 // Test that the right values are returned when the dialog is canceled. 247 add_task(async function testCancelDialogReturnValues() { 248 let [win, retVals] = await openDeleteCertConfirmDialog( 249 "ca_tab" /* arbitrary */ 250 ); 251 info("Canceling dialog"); 252 win.document.getElementById("deleteCertificate").cancelDialog(); 253 await BrowserTestUtils.windowClosed(win); 254 255 Assert.ok( 256 !retVals.deleteConfirmed, 257 "Return value should signal user did not accept" 258 ); 259 });