tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });