diff options
Diffstat (limited to 'security/manager/ssl/ClientAuthDialogService.sys.mjs')
-rw-r--r-- | security/manager/ssl/ClientAuthDialogService.sys.mjs | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/security/manager/ssl/ClientAuthDialogService.sys.mjs b/security/manager/ssl/ClientAuthDialogService.sys.mjs new file mode 100644 index 0000000000..7019dcc5cd --- /dev/null +++ b/security/manager/ssl/ClientAuthDialogService.sys.mjs @@ -0,0 +1,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); + }, +}; |