Dialogue

var openDialogOptions = 'chrome=yes,modal=yes,dialog=yes,dependant=yes,centerscreen=yes';
var openDialogArgs = {location: 'https://thewebsite.com/', prefetchCert:null, exceptionAdded:false };
window.openDialog('chrome://pippki/content/exceptionDialog.xul', 'exceptionDialog', openDialogOptions, openDialogArgs);

if (openDialogArgs.exceptionAdded) {
  // redo request or other...
}


security/manager/ssl/src/nsNSSIOLayer.cpp

static nsresult nsHandleInvalidCertError(...) 
{
  ...
  // What mechanism is used to inform the user?
  // The highest priority has the "external error reporting" feature,
  // if set, we'll provide the strings to be used by the nsINSSErrorsService

  PRBool external = PR_FALSE;
  socketInfo->GetExternalErrorReporting(&external);
~~
  nsString formattedString;
  rv = getInvalidCertErrorMessage(multipleCollectedErrors, errorCodeToReport,
                                  errTrust, errMismatch, errExpired,
                                  hostU, hostWithPortU, port,~
                                  ix509, external, nssComponent, formattedString);

  if (external)
  {
    socketInfo->SetErrorMessage(formattedString.get());
  }
  else 
  {
    nsPSMUITracker tracker;
    if (tracker.isUIForbidden()) {
      rv = NS_ERROR_NOT_AVAILABLE;
    }
    else {
      rv = displayAlert(formattedString, socketInfo);
    }
  }
  return rv;
}

static nsresult getInvalidCertErrorMessage(...)
{
 ...
     AppendErrorTextUntrusted(errTrust, host, ix509, component, returnedMessage);
 ...
}

static void AppendErrorTextUntrusted(...)
{
  errorID = "certErrorTrust_UnknownIssuer";
  
}

security/manager/locales/en-US/chrome/pipnss/pipnss.properties
certErrorTrust_UnknownIssuer=The certificate is not trusted because the issuer certificate is unknown.

nsHandleInvalidCertError regarde socketInfo->GetExternalErrorReporting. Un socketInfo a un attribut privé mExternalErrorReporting qui peut être changé par SetExternalErrorReporting ou par la fonction EnsureDocShellDependentStuffKnown(). On peut aussi bypassé ce système en implémentant un NotificationCallbacks() et en le plaçant sur le channel.notificationCallbacks d'un objet XMLHttpRequest ouvert.

On peut voir le commentaire suivant:

  // Are we running within a context that wants external SSL error reporting?
  // We'll look at the presence of a security UI object inside docshell.
  // If the docshell wants the lock icon, you'll get the ssl error pages, too.
  // This is helpful to distinguish from all other contexts, like mail windows,
  // or any other SSL connections running in the background.
  // We must query it now and remember, because fatal SSL errors will come~
  // with a socket close, and the socket transport might detach the callbacks~
  // instance prior to our error reporting.

  ...
  nsISecureBrowserUI* secureUI;
  proxiedDocShell->GetSecurityUI(&secureUI);
  if (secureUI)
  { 
    ...
  }

Piste de solution...

var gCert = null;
var gTargetHost = '';

function badCertListener() {}
badCertListener.prototype = { 
  getInterface: function (aIID) { return this.QueryInterface(aIID); },  
  QueryInterface: function(aIID) {
    if (aIID.equals(Components.interfaces.nsIBadCertListener2) ||
        aIID.equals(Components.interfaces.nsIInterfaceRequestor) ||
        aIID.equals(Components.interfaces.nsISupports))
      return this;

    throw Components.results.NS_ERROR_NO_INTERFACE;
  },
  handle_test_result: function () {
    if (gSSLStatus) {
      alert('bad certificate, add your code here to call exceptionDialog.xul');
      gCert = gSSLStatus.QueryInterface(Components.interfaces.nsISSLStatus).serverCert;
    }
  },
  notifyCertProblem: function MSR_notifyCertProblem(socketInfo, sslStatus, targetHost) {
    gBroken = true;
    gSSLStatus = sslStatus;
    gTargetHost = targetHost;
    this.handle_test_result();
    return true; // suppress error UI
  }
}


var req = new XMLHttpRequest();
req.open('POST', url, true);
req.channel.notificationCallbacks = new badCertListener();
try {
  gCert = null;
  req.send(null);
} catch(e) {
  if (gCert != null && e.result && e.result == 2147500037) {
    alert('catch exception for invalid cert for ' + gTargetHost)
  }
}