Bug 855543 - Opening app content that generates a certificate error results in the 'app not loading properly' modal dialog on top of the cert error handling page, making it impossible to provide a cert exception to the web content. r=jlebar

This commit is contained in:
Vivien Nicolas 2013-05-23 17:52:05 +02:00
Родитель 85b2421b89
Коммит 75a787ff2a
2 изменённых файлов: 101 добавлений и 5 удалений

Просмотреть файл

@ -41,6 +41,52 @@ function sendAsyncMsg(msg, data) {
sendAsyncMessage('browser-element-api:call', data);
}
let CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page';
let NS_ERROR_MODULE_BASE_OFFSET = 0x45;
let NS_ERROR_MODULE_SECURITY= 21;
function NS_ERROR_GET_MODULE(err) {
return ((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff)
}
function NS_ERROR_GET_CODE(err) {
return ((err) & 0xffff);
}
let SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
let SEC_ERROR_UNKNOWN_ISSUER = (SEC_ERROR_BASE + 13);
let SEC_ERROR_CA_CERT_INVALID = (SEC_ERROR_BASE + 36);
let SEC_ERROR_UNTRUSTED_ISSUER = (SEC_ERROR_BASE + 20);
let SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE = (SEC_ERROR_BASE + 30);
let SEC_ERROR_UNTRUSTED_CERT = (SEC_ERROR_BASE + 21);
let SEC_ERROR_INADEQUATE_KEY_USAGE = (SEC_ERROR_BASE + 90);
let SEC_ERROR_EXPIRED_CERTIFICATE = (SEC_ERROR_BASE + 11);
let SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = (SEC_ERROR_BASE + 176);
let SSL_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE;
let SSL_ERROR_BAD_CERT_DOMAIN = (SSL_ERROR_BASE + 12);
function getErrorClass(errorCode) {
let NSPRCode = -1 * NS_ERROR_GET_CODE(errorCode);
switch (NSPRCode) {
case SEC_ERROR_UNKNOWN_ISSUER:
case SEC_ERROR_CA_CERT_INVALID:
case SEC_ERROR_UNTRUSTED_ISSUER:
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
case SEC_ERROR_UNTRUSTED_CERT:
case SEC_ERROR_INADEQUATE_KEY_USAGE:
case SSL_ERROR_BAD_CERT_DOMAIN:
case SEC_ERROR_EXPIRED_CERTIFICATE:
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
return Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT;
default:
return Ci.nsINSSErrorsService.ERROR_CLASS_SSL_PROTOCOL;
}
return null;
}
/**
* The BrowserElementChild implements one half of <iframe mozbrowser>.
* (The other half is, unsurprisingly, BrowserElementParent.)
@ -827,6 +873,24 @@ BrowserElementChild.prototype = {
return;
}
if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY &&
getErrorClass(status) == Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT) {
// XXX Is there a point firing the event if the error page is not
// certerror? If yes, maybe we should add a property to the
// event to to indicate whether there is a custom page. That would
// let the embedder have more control over the desired behavior.
var errorPage = null;
try {
errorPage = Services.prefs.getCharPref(CERTIFICATE_ERROR_PAGE_PREF);
} catch(e) {}
if (errorPage == 'certerror') {
sendAsyncMsg('error', { type: 'certerror' });
return;
}
}
// TODO See nsDocShell::DisplayLoadError for a list of all the error
// codes (the status param) we should eventually handle here.
sendAsyncMsg('error', { type: 'other' });

Просмотреть файл

@ -9,18 +9,50 @@ SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
var iframe = null;
function runTest() {
var iframe = document.createElement('iframe');
iframe = document.createElement('iframe');
SpecialPowers.wrap(iframe).mozbrowser = true;
document.body.appendChild(iframe);
iframe.addEventListener("mozbrowsererror", function(e) {
checkForGenericError();
}
function checkForGenericError() {
iframe.addEventListener("mozbrowsererror", function onGenericError(e) {
iframe.removeEventListener(e.type, onGenericError);
ok(true, "Got mozbrowsererror event.");
ok(e.detail.type, "Event's detail has a |type| param.");
SimpleTest.finish();
ok(e.detail.type == "other", "Event's detail has a |type| param with the value '" + e.detail.type + "'.");
checkForExpiredCertificateError();
});
iframe.src = "http://this_is_not_a_domain.example.com";
}
function checkForExpiredCertificateError() {
iframe.addEventListener("mozbrowsererror", function onCertError(e) {
iframe.removeEventListener(e.type, onCertError);
ok(true, "Got mozbrowsererror event.");
ok(e.detail.type == "certerror", "Event's detail has a |type| param with the value '" + e.detail.type + "'.");
checkForNoCertificateError();
});
iframe.src = "https://expired.example.com";
document.body.appendChild(iframe);
}
function checkForNoCertificateError() {
iframe.addEventListener("mozbrowsererror", function onCertError(e) {
iframe.removeEventListener(e.type, onCertError);
ok(true, "Got mozbrowsererror event.");
ok(e.detail.type == "certerror", "Event's detail has a |type| param with the value '" + e.detail.type + "'.");
SimpleTest.finish();
});
iframe.src = "https://nocert.example.com";
}
addEventListener('testready', runTest);