summaryrefslogtreecommitdiffstats
path: root/security/manager/ssl/ClientAuthDialogService.sys.mjs
blob: 7019dcc5cd74489f57a558f73e38ba43bfacb79b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// ClientAuthDialogService implements nsIClientAuthDialogService, and aims to
// open a dialog asking the user to select a client authentication certificate.
// Ideally the dialog will be tab-modal to the tab corresponding to the load
// that resulted in the request for the client authentication certificate.
export function ClientAuthDialogService() {}

// Given a loadContext (CanonicalBrowsingContext), attempts to return a
// TabDialogBox for the browser corresponding to loadContext.
function getTabDialogBoxForLoadContext(loadContext) {
  let tabBrowser = loadContext?.topFrameElement?.getTabBrowser();
  if (!tabBrowser) {
    return null;
  }
  for (let browser of tabBrowser.browsers) {
    if (browser.browserId == loadContext.top?.browserId) {
      return tabBrowser.getTabDialogBox(browser);
    }
  }
  return null;
}

ClientAuthDialogService.prototype = {
  classID: Components.ID("{d7d2490d-2640-411b-9f09-a538803c11ee}"),
  QueryInterface: ChromeUtils.generateQI(["nsIClientAuthDialogService"]),

  chooseCertificate: function ClientAuthDialogService_chooseCertificate(
    hostname,
    certArray,
    loadContext,
    callback
  ) {
    const clientAuthAskURI = "chrome://pippki/content/clientauthask.xhtml";
    let retVals = { cert: null, rememberDecision: false };
    // First attempt to find a TabDialogBox for the loadContext. This allows
    // for a tab-modal dialog specific to the tab causing the load, which is a
    // better user experience.
    let tabDialogBox = getTabDialogBoxForLoadContext(loadContext);
    if (tabDialogBox) {
      tabDialogBox
        .open(clientAuthAskURI, {}, { hostname, certArray, retVals })
        .closedPromise.then(() => {
          callback.certificateChosen(retVals.cert, retVals.rememberDecision);
        });
      return;
    }
    // Otherwise, attempt to open a window-modal dialog on the window that at
    // least has the tab the load is occurring in.
    let browserWindow = loadContext?.topFrameElement?.ownerGlobal;
    // Failing that, open a window-modal dialog on the most recent window.
    if (!browserWindow) {
      browserWindow = Services.wm.getMostRecentBrowserWindow();
    }
    if (browserWindow) {
      browserWindow.gDialogBox
        .open(clientAuthAskURI, { hostname, certArray, retVals })
        .then(() => {
          callback.certificateChosen(retVals.cert, retVals.rememberDecision);
        });
      return;
    }
    // Otherwise, continue the connection with no certificate.
    callback.certificateChosen(null, false);
  },
};