зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1492498 - Make certificate exceptions on the new cert error pages permanent by default. r=nhnt11,keeler
This includes a new test for the feature and a bit of test cleanup to factor out all exception related tests into their own test file. Differential Revision: https://phabricator.services.mozilla.com/D17109 --HG-- rename : browser/base/content/test/about/browser_aboutCertError.js => browser/base/content/test/about/browser_aboutCertError_exception.js extra : moz-landing-system : lando
This commit is contained in:
Родитель
514415e0a0
Коммит
ad87a838f7
|
@ -969,6 +969,7 @@ pref("browser.security.newcerterrorpage.mitm.enabled", false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pref("security.certerrors.recordEventTelemetry", true);
|
pref("security.certerrors.recordEventTelemetry", true);
|
||||||
|
pref("security.certerrors.permanentOverride", true);
|
||||||
|
|
||||||
// Whether to start the private browsing mode at application startup
|
// Whether to start the private browsing mode at application startup
|
||||||
pref("browser.privatebrowsing.autostart", false);
|
pref("browser.privatebrowsing.autostart", false);
|
||||||
|
|
|
@ -2958,12 +2958,14 @@ var BrowserOnClick = {
|
||||||
flags |= overrideService.ERROR_TIME;
|
flags |= overrideService.ERROR_TIME;
|
||||||
}
|
}
|
||||||
let uri = Services.uriFixup.createFixupURI(location, 0);
|
let uri = Services.uriFixup.createFixupURI(location, 0);
|
||||||
|
let permanentOverride =
|
||||||
|
Services.prefs.getBoolPref("security.certerrors.permanentOverride");
|
||||||
cert = securityInfo.serverCert;
|
cert = securityInfo.serverCert;
|
||||||
overrideService.rememberValidityOverride(
|
overrideService.rememberValidityOverride(
|
||||||
uri.asciiHost, uri.port,
|
uri.asciiHost, uri.port,
|
||||||
cert,
|
cert,
|
||||||
flags,
|
flags,
|
||||||
true);
|
!permanentOverride);
|
||||||
browser.reload();
|
browser.reload();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ prefs =
|
||||||
|
|
||||||
[browser_aboutCertError.js]
|
[browser_aboutCertError.js]
|
||||||
[browser_aboutCertError_clockSkew.js]
|
[browser_aboutCertError_clockSkew.js]
|
||||||
|
[browser_aboutCertError_exception.js]
|
||||||
[browser_aboutCertError_telemetry.js]
|
[browser_aboutCertError_telemetry.js]
|
||||||
[browser_aboutHome_search_POST.js]
|
[browser_aboutHome_search_POST.js]
|
||||||
[browser_aboutHome_search_composing.js]
|
[browser_aboutHome_search_composing.js]
|
||||||
|
|
|
@ -52,34 +52,6 @@ add_task(async function checkReturnToAboutHome() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function checkExceptionDialogButton() {
|
|
||||||
Services.prefs.setBoolPref(PREF_NEW_CERT_ERRORS, true);
|
|
||||||
info("Loading a bad cert page and making sure the exceptionDialogButton directly adds an exception");
|
|
||||||
let tab = await openErrorPage(BAD_CERT);
|
|
||||||
let browser = tab.linkedBrowser;
|
|
||||||
let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT);
|
|
||||||
info("Clicking the exceptionDialogButton in advanced panel");
|
|
||||||
await ContentTask.spawn(browser, null, async function() {
|
|
||||||
let doc = content.document;
|
|
||||||
let exceptionButton = doc.getElementById("exceptionDialogButton");
|
|
||||||
exceptionButton.click();
|
|
||||||
});
|
|
||||||
|
|
||||||
info("Loading the url after adding exception");
|
|
||||||
await loaded;
|
|
||||||
|
|
||||||
await ContentTask.spawn(browser, null, async function() {
|
|
||||||
let doc = content.document;
|
|
||||||
ok(!doc.documentURI.startsWith("about:certerror"), "Exception has been added");
|
|
||||||
});
|
|
||||||
|
|
||||||
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
|
|
||||||
.getService(Ci.nsICertOverrideService);
|
|
||||||
certOverrideService.clearValidityOverride("expired.example.com", -1);
|
|
||||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
|
||||||
Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function checkReturnToPreviousPage() {
|
add_task(async function checkReturnToPreviousPage() {
|
||||||
info("Loading a bad cert page and making sure 'return to previous page' goes back");
|
info("Loading a bad cert page and making sure 'return to previous page' goes back");
|
||||||
for (let useFrame of [false, true]) {
|
for (let useFrame of [false, true]) {
|
||||||
|
@ -128,43 +100,6 @@ add_task(async function checkReturnToPreviousPage() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function checkBadStsCert() {
|
|
||||||
info("Loading a badStsCert and making sure exception button doesn't show up");
|
|
||||||
|
|
||||||
for (let useFrame of [false, true]) {
|
|
||||||
let tab = await openErrorPage(BAD_STS_CERT, useFrame);
|
|
||||||
let browser = tab.linkedBrowser;
|
|
||||||
|
|
||||||
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
|
|
||||||
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
|
|
||||||
let exceptionButton = doc.getElementById("exceptionDialogButton");
|
|
||||||
ok(ContentTaskUtils.is_hidden(exceptionButton), "Exception button is hidden.");
|
|
||||||
});
|
|
||||||
|
|
||||||
let message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
|
|
||||||
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
|
|
||||||
let advancedButton = doc.getElementById("advancedButton");
|
|
||||||
advancedButton.click();
|
|
||||||
return doc.getElementById("badCertTechnicalInfo").textContent;
|
|
||||||
});
|
|
||||||
if (Services.prefs.getBoolPref(PREF_NEW_CERT_ERRORS)) {
|
|
||||||
ok(message.includes("SSL_ERROR_BAD_CERT_DOMAIN"), "Didn't find SSL_ERROR_BAD_CERT_DOMAIN.");
|
|
||||||
ok(message.includes("The certificate is only valid for"), "Didn't find error message.");
|
|
||||||
ok(message.includes("a certificate that is not valid for"), "Didn't find error message.");
|
|
||||||
ok(message.includes("badchain.include-subdomains.pinning.example.com"), "Didn't find domain in error message.");
|
|
||||||
|
|
||||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ok(message.includes("SSL_ERROR_BAD_CERT_DOMAIN"), "Didn't find SSL_ERROR_BAD_CERT_DOMAIN.");
|
|
||||||
ok(message.includes("The certificate is only valid for"), "Didn't find error message.");
|
|
||||||
ok(message.includes("uses an invalid security certificate"), "Didn't find error message.");
|
|
||||||
ok(message.includes("badchain.include-subdomains.pinning.example.com"), "Didn't find domain in error message.");
|
|
||||||
|
|
||||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// This checks that the appinfo.appBuildID starts with a date string,
|
// This checks that the appinfo.appBuildID starts with a date string,
|
||||||
// which is required for the misconfigured system time check.
|
// which is required for the misconfigured system time check.
|
||||||
add_task(async function checkAppBuildIDIsDate() {
|
add_task(async function checkAppBuildIDIsDate() {
|
||||||
|
@ -240,41 +175,6 @@ add_task(async function checkAdvancedDetails() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function checkhideAddExceptionButtonViaPref() {
|
|
||||||
info("Loading a bad cert page and verifying the pref security.certerror.hideAddException");
|
|
||||||
Services.prefs.setBoolPref("security.certerror.hideAddException", true);
|
|
||||||
|
|
||||||
for (let useFrame of [false, true]) {
|
|
||||||
let tab = await openErrorPage(BAD_CERT, useFrame);
|
|
||||||
let browser = tab.linkedBrowser;
|
|
||||||
|
|
||||||
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
|
|
||||||
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
|
|
||||||
|
|
||||||
let exceptionButton = doc.querySelector(".exceptionDialogButtonContainer");
|
|
||||||
ok(ContentTaskUtils.is_hidden(exceptionButton), "Exception button is hidden.");
|
|
||||||
});
|
|
||||||
|
|
||||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
|
||||||
}
|
|
||||||
|
|
||||||
Services.prefs.clearUserPref("security.certerror.hideAddException");
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function checkhideAddExceptionButtonInFrames() {
|
|
||||||
info("Loading a bad cert page in a frame and verifying it's hidden.");
|
|
||||||
let tab = await openErrorPage(BAD_CERT, true);
|
|
||||||
let browser = tab.linkedBrowser;
|
|
||||||
|
|
||||||
await ContentTask.spawn(browser, null, async function() {
|
|
||||||
let doc = content.document.querySelector("iframe").contentDocument;
|
|
||||||
let exceptionButton = doc.getElementById("exceptionDialogButton");
|
|
||||||
ok(ContentTaskUtils.is_hidden(exceptionButton), "Exception button is hidden.");
|
|
||||||
});
|
|
||||||
|
|
||||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function checkAdvancedDetailsForHSTS() {
|
add_task(async function checkAdvancedDetailsForHSTS() {
|
||||||
info("Loading a bad STS cert page and verifying the advanced details section");
|
info("Loading a bad STS cert page and verifying the advanced details section");
|
||||||
for (let useFrame of [false, true]) {
|
for (let useFrame of [false, true]) {
|
||||||
|
@ -412,35 +312,3 @@ add_task(async function checkViewCertificate() {
|
||||||
}
|
}
|
||||||
Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
|
Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
|
||||||
});
|
});
|
||||||
|
|
||||||
function getCertChain(securityInfoAsString) {
|
|
||||||
let certChain = "";
|
|
||||||
const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
|
||||||
.getService(Ci.nsISerializationHelper);
|
|
||||||
let securityInfo = serhelper.deserializeObject(securityInfoAsString);
|
|
||||||
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
|
|
||||||
for (let cert of securityInfo.failedCertChain.getEnumerator()) {
|
|
||||||
certChain += getPEMString(cert);
|
|
||||||
}
|
|
||||||
return certChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDERString(cert) {
|
|
||||||
var length = {};
|
|
||||||
var derArray = cert.getRawDER(length);
|
|
||||||
var derString = "";
|
|
||||||
for (var i = 0; i < derArray.length; i++) {
|
|
||||||
derString += String.fromCharCode(derArray[i]);
|
|
||||||
}
|
|
||||||
return derString;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPEMString(cert) {
|
|
||||||
var derb64 = btoa(getDERString(cert));
|
|
||||||
// Wrap the Base64 string into lines of 64 characters,
|
|
||||||
// with CRLF line breaks (as specified in RFC 1421).
|
|
||||||
var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
|
|
||||||
return "-----BEGIN CERTIFICATE-----\r\n"
|
|
||||||
+ wrapped
|
|
||||||
+ "\r\n-----END CERTIFICATE-----\r\n";
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const BAD_CERT = "https://expired.example.com/";
|
||||||
|
const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
|
||||||
|
const PREF_NEW_CERT_ERRORS = "browser.security.newcerterrorpage.enabled";
|
||||||
|
const PREF_PERMANENT_OVERRIDE = "security.certerrors.permanentOverride";
|
||||||
|
|
||||||
|
add_task(async function checkExceptionDialogButton() {
|
||||||
|
Services.prefs.setBoolPref(PREF_NEW_CERT_ERRORS, true);
|
||||||
|
info("Loading a bad cert page and making sure the exceptionDialogButton directly adds an exception");
|
||||||
|
let tab = await openErrorPage(BAD_CERT);
|
||||||
|
let browser = tab.linkedBrowser;
|
||||||
|
let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT);
|
||||||
|
info("Clicking the exceptionDialogButton in advanced panel");
|
||||||
|
await ContentTask.spawn(browser, null, async function() {
|
||||||
|
let doc = content.document;
|
||||||
|
let exceptionButton = doc.getElementById("exceptionDialogButton");
|
||||||
|
exceptionButton.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Loading the url after adding exception");
|
||||||
|
await loaded;
|
||||||
|
|
||||||
|
await ContentTask.spawn(browser, null, async function() {
|
||||||
|
let doc = content.document;
|
||||||
|
ok(!doc.documentURI.startsWith("about:certerror"), "Exception has been added");
|
||||||
|
});
|
||||||
|
|
||||||
|
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
|
||||||
|
.getService(Ci.nsICertOverrideService);
|
||||||
|
certOverrideService.clearValidityOverride("expired.example.com", -1);
|
||||||
|
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||||
|
Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function checkPermanentExceptionPref() {
|
||||||
|
Services.prefs.setBoolPref(PREF_NEW_CERT_ERRORS, true);
|
||||||
|
info("Loading a bad cert page and making sure the permanent state of exceptions can be controlled via pref");
|
||||||
|
|
||||||
|
for (let permanentOverride of [false, true]) {
|
||||||
|
Services.prefs.setBoolPref(PREF_PERMANENT_OVERRIDE, permanentOverride);
|
||||||
|
|
||||||
|
let tab = await openErrorPage(BAD_CERT);
|
||||||
|
let browser = tab.linkedBrowser;
|
||||||
|
let loaded = BrowserTestUtils.browserLoaded(browser, false, BAD_CERT);
|
||||||
|
info("Clicking the exceptionDialogButton in advanced panel");
|
||||||
|
let securityInfoAsString = await ContentTask.spawn(browser, null, async function() {
|
||||||
|
let doc = content.document;
|
||||||
|
let exceptionButton = doc.getElementById("exceptionDialogButton");
|
||||||
|
exceptionButton.click();
|
||||||
|
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||||
|
.getService(Ci.nsISerializationHelper);
|
||||||
|
let serializable = content.docShell.failedChannel.securityInfo
|
||||||
|
.QueryInterface(Ci.nsITransportSecurityInfo)
|
||||||
|
.QueryInterface(Ci.nsISerializable);
|
||||||
|
return serhelper.serializeToString(serializable);
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Loading the url after adding exception");
|
||||||
|
await loaded;
|
||||||
|
|
||||||
|
await ContentTask.spawn(browser, null, async function() {
|
||||||
|
let doc = content.document;
|
||||||
|
ok(!doc.documentURI.startsWith("about:certerror"), "Exception has been added");
|
||||||
|
});
|
||||||
|
|
||||||
|
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
|
||||||
|
.getService(Ci.nsICertOverrideService);
|
||||||
|
|
||||||
|
let isTemporary = {};
|
||||||
|
let cert = getSecurityInfo(securityInfoAsString).serverCert;
|
||||||
|
let hasException =
|
||||||
|
certOverrideService.hasMatchingOverride("expired.example.com", -1, cert, {}, isTemporary);
|
||||||
|
ok(hasException, "Has stored an exception for the page.");
|
||||||
|
is(isTemporary.value, !permanentOverride,
|
||||||
|
`Has stored a ${permanentOverride ? "permanent" : "temporary"} exception for the page.`);
|
||||||
|
|
||||||
|
certOverrideService.clearValidityOverride("expired.example.com", -1);
|
||||||
|
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.prefs.clearUserPref(PREF_PERMANENT_OVERRIDE);
|
||||||
|
Services.prefs.clearUserPref(PREF_NEW_CERT_ERRORS);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function checkBadStsCert() {
|
||||||
|
info("Loading a badStsCert and making sure exception button doesn't show up");
|
||||||
|
|
||||||
|
for (let useFrame of [false, true]) {
|
||||||
|
let tab = await openErrorPage(BAD_STS_CERT, useFrame);
|
||||||
|
let browser = tab.linkedBrowser;
|
||||||
|
|
||||||
|
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
|
||||||
|
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
|
||||||
|
let exceptionButton = doc.getElementById("exceptionDialogButton");
|
||||||
|
ok(ContentTaskUtils.is_hidden(exceptionButton), "Exception button is hidden.");
|
||||||
|
});
|
||||||
|
|
||||||
|
let message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
|
||||||
|
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
|
||||||
|
let advancedButton = doc.getElementById("advancedButton");
|
||||||
|
advancedButton.click();
|
||||||
|
return doc.getElementById("badCertTechnicalInfo").textContent;
|
||||||
|
});
|
||||||
|
if (Services.prefs.getBoolPref(PREF_NEW_CERT_ERRORS)) {
|
||||||
|
ok(message.includes("SSL_ERROR_BAD_CERT_DOMAIN"), "Didn't find SSL_ERROR_BAD_CERT_DOMAIN.");
|
||||||
|
ok(message.includes("The certificate is only valid for"), "Didn't find error message.");
|
||||||
|
ok(message.includes("a certificate that is not valid for"), "Didn't find error message.");
|
||||||
|
ok(message.includes("badchain.include-subdomains.pinning.example.com"), "Didn't find domain in error message.");
|
||||||
|
|
||||||
|
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ok(message.includes("SSL_ERROR_BAD_CERT_DOMAIN"), "Didn't find SSL_ERROR_BAD_CERT_DOMAIN.");
|
||||||
|
ok(message.includes("The certificate is only valid for"), "Didn't find error message.");
|
||||||
|
ok(message.includes("uses an invalid security certificate"), "Didn't find error message.");
|
||||||
|
ok(message.includes("badchain.include-subdomains.pinning.example.com"), "Didn't find domain in error message.");
|
||||||
|
|
||||||
|
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function checkhideAddExceptionButtonViaPref() {
|
||||||
|
info("Loading a bad cert page and verifying the pref security.certerror.hideAddException");
|
||||||
|
Services.prefs.setBoolPref("security.certerror.hideAddException", true);
|
||||||
|
|
||||||
|
for (let useFrame of [false, true]) {
|
||||||
|
let tab = await openErrorPage(BAD_CERT, useFrame);
|
||||||
|
let browser = tab.linkedBrowser;
|
||||||
|
|
||||||
|
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
|
||||||
|
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
|
||||||
|
|
||||||
|
let exceptionButton = doc.querySelector(".exceptionDialogButtonContainer");
|
||||||
|
ok(ContentTaskUtils.is_hidden(exceptionButton), "Exception button is hidden.");
|
||||||
|
});
|
||||||
|
|
||||||
|
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.prefs.clearUserPref("security.certerror.hideAddException");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function checkhideAddExceptionButtonInFrames() {
|
||||||
|
info("Loading a bad cert page in a frame and verifying it's hidden.");
|
||||||
|
let tab = await openErrorPage(BAD_CERT, true);
|
||||||
|
let browser = tab.linkedBrowser;
|
||||||
|
|
||||||
|
await ContentTask.spawn(browser, null, async function() {
|
||||||
|
let doc = content.document.querySelector("iframe").contentDocument;
|
||||||
|
let exceptionButton = doc.getElementById("exceptionDialogButton");
|
||||||
|
ok(ContentTaskUtils.is_hidden(exceptionButton), "Exception button is hidden.");
|
||||||
|
});
|
||||||
|
|
||||||
|
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||||
|
});
|
|
@ -4,6 +4,43 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
FormHistory: "resource://gre/modules/FormHistory.jsm",
|
FormHistory: "resource://gre/modules/FormHistory.jsm",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getSecurityInfo(securityInfoAsString) {
|
||||||
|
const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||||
|
.getService(Ci.nsISerializationHelper);
|
||||||
|
let securityInfo = serhelper.deserializeObject(securityInfoAsString);
|
||||||
|
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
|
||||||
|
return securityInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCertChain(securityInfoAsString) {
|
||||||
|
let certChain = "";
|
||||||
|
let securityInfo = getSecurityInfo(securityInfoAsString);
|
||||||
|
for (let cert of securityInfo.failedCertChain.getEnumerator()) {
|
||||||
|
certChain += getPEMString(cert);
|
||||||
|
}
|
||||||
|
return certChain;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDERString(cert) {
|
||||||
|
var length = {};
|
||||||
|
var derArray = cert.getRawDER(length);
|
||||||
|
var derString = "";
|
||||||
|
for (var i = 0; i < derArray.length; i++) {
|
||||||
|
derString += String.fromCharCode(derArray[i]);
|
||||||
|
}
|
||||||
|
return derString;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPEMString(cert) {
|
||||||
|
var derb64 = btoa(getDERString(cert));
|
||||||
|
// Wrap the Base64 string into lines of 64 characters,
|
||||||
|
// with CRLF line breaks (as specified in RFC 1421).
|
||||||
|
var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
|
||||||
|
return "-----BEGIN CERTIFICATE-----\r\n"
|
||||||
|
+ wrapped
|
||||||
|
+ "\r\n-----END CERTIFICATE-----\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
function injectErrorPageFrame(tab, src) {
|
function injectErrorPageFrame(tab, src) {
|
||||||
return ContentTask.spawn(tab.linkedBrowser, {frameSrc: src}, async function({frameSrc}) {
|
return ContentTask.spawn(tab.linkedBrowser, {frameSrc: src}, async function({frameSrc}) {
|
||||||
let loaded = ContentTaskUtils.waitForEvent(content.wrappedJSObject, "DOMFrameContentLoaded");
|
let loaded = ContentTaskUtils.waitForEvent(content.wrappedJSObject, "DOMFrameContentLoaded");
|
||||||
|
|
Загрузка…
Ссылка в новой задаче