Bug 1241455 Send TLS Error Reports for subresources r=past, Gijs, mcmanus

This patch makes use of the security reporter component (which hasn't landed yet
 - see blockers) to allow automatic TLS error reports to be sent directly from
nsHttpChannel.cpp rather than sending them from browser.js. This allows failed
connections for subresources to be reported.

Some of the report sending from browser.js was retained to allow reports to be
sent at the time a user enables reporting. This has been modified to also make
use of the component.

Since the patient is on the table, I've also taken the opportunity to
remove the retry and status bits from aboutCertError.xhtml and
aboutNetError.xhtml - which removes a bunch of code and simplifies things a bit.

The mochitests have been modified to cope with the fact that the UI does not
update with report sending / report failures - instead, success and failure are
determined by examining the response seen from the server from within the test.
This commit is contained in:
Mark Goodwin 2016-02-01 11:18:50 +00:00
parent 851cfc945a
commit 80805376be
10 changed files with 147 additions and 329 deletions

View File

@ -144,12 +144,6 @@
}
}
function sendErrorReport() {
var event = new CustomEvent("AboutNetErrorSendReport", {bubbles:true});
document.dispatchEvent(event);
}
function initPage()
{
var err = getErrorCode();
@ -260,13 +254,7 @@
var event = new CustomEvent("AboutNetErrorSetAutomatic",
{bubbles:true, detail:evt.target.checked});
document.dispatchEvent(event);
if (evt.target.checked) {
sendErrorReport();
}
}, false);
var retryBtn = document.getElementById('reportCertificateErrorRetry');
retryBtn.addEventListener('click', sendErrorReport, false);
}
}
if (getErrorCode() == "weakCryptoUsed" || getErrorCode() == "sslv3Used") {
@ -527,12 +515,6 @@
<p>
<input type="checkbox" id="automaticallyReportInFuture" />
<label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic2;</label>
<span id="reportingState">
<button id="reportCertificateErrorRetry">&errorReporting.tryAgain;</button>
<span id="reportSendingMessage">&errorReporting.sending;</span>
<span id="reportSentMessage">&errorReporting.sent;</span>
</span>
</p>
</div>

View File

@ -96,13 +96,6 @@
}));
});
var retryBtn = document.getElementById("reportCertificateErrorRetry");
retryBtn.addEventListener("click", function () {
document.dispatchEvent(new CustomEvent("AboutCertErrorSendReport", {
bubbles: true
}));
});
addEventListener("AboutCertErrorOptions", function (event) {
var options = JSON.parse(event.detail);
if (options && options.enabled) {
@ -287,12 +280,6 @@
<p>
<input type="checkbox" id="automaticallyReportInFuture" />
<label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic;</label>
<span id="reportingState">
<button id="reportCertificateErrorRetry">&errorReporting.tryAgain;</button>
<span id="reportSendingMessage">&errorReporting.sending;</span>
<span id="reportSentMessage">&errorReporting.sent;</span>
</span>
</p>
</div>

View File

@ -2711,100 +2711,23 @@ var BrowserOnClick = {
},
onSSLErrorReport: function(browser, documentURI, location, securityInfo) {
function showReportStatus(reportStatus) {
gBrowser.selectedBrowser
.messageManager
.sendAsyncMessage("Browser:SSLErrorReportStatus",
{
reportStatus: reportStatus,
documentURI: documentURI
});
}
if (!Services.prefs.getBoolPref("security.ssl.errorReporting.enabled")) {
showReportStatus("error");
Cu.reportError("User requested certificate error report sending, but certificate error reporting is disabled");
return;
}
let bin = TLS_ERROR_REPORT_TELEMETRY_MANUAL_SEND;
if (Services.prefs.getBoolPref("security.ssl.errorReporting.automatic")) {
bin = TLS_ERROR_REPORT_TELEMETRY_AUTO_SEND;
}
Services.telemetry.getHistogramById("TLS_ERROR_REPORT_UI").add(bin);
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let transportSecurityInfo = serhelper.deserializeObject(securityInfo);
transportSecurityInfo.QueryInterface(Ci.nsITransportSecurityInfo)
showReportStatus("activity");
/*
* Requested info for the report:
* - Domain of bad connection
* - Error type (e.g. Pinning, domain mismatch, etc)
* - Cert chain (at minimum, same data to distrust each cert in the
* chain)
* - Request data (e.g. User Agent, IP, Timestamp)
*
* The request data should be added to the report by the receiving server.
*/
// Convert the nsIX509CertList into a format that can be parsed into
// JSON
let asciiCertChain = [];
if (transportSecurityInfo.failedCertChain) {
let certs = transportSecurityInfo.failedCertChain.getEnumerator();
while (certs.hasMoreElements()) {
let cert = certs.getNext();
cert.QueryInterface(Ci.nsIX509Cert);
asciiCertChain.push(btoa(getDERString(cert)));
}
}
let report = {
hostname: location.hostname,
port: location.port,
timestamp: Math.round(Date.now() / 1000),
errorCode: transportSecurityInfo.errorCode,
failedCertChain: asciiCertChain,
userAgent: window.navigator.userAgent,
version: 1,
build: gAppInfo.appBuildID,
product: gAppInfo.name,
channel: UpdateUtils.UpdateChannel
}
let reportURL = Services.prefs.getCharPref("security.ssl.errorReporting.url");
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
try {
xhr.open("POST", reportURL);
} catch (e) {
Cu.reportError("xhr.open exception", e);
showReportStatus("error");
}
xhr.onerror = function (e) {
// error making request to reportURL
Cu.reportError("xhr onerror", e);
showReportStatus("error");
};
xhr.onload = function (event) {
if (xhr.status !== 201 && xhr.status !== 0) {
// request returned non-success status
Cu.reportError("xhr returned failure code", xhr.status);
showReportStatus("error");
} else {
showReportStatus("complete");
}
};
xhr.send(JSON.stringify(report));
let errorReporter = Cc["@mozilla.org/securityreporter;1"]
.getService(Ci.nsISecurityReporter);
// if location.port is the empty string, set to -1 (for consistency with
// port values from nsIURI)
let port = location.port === "" ? -1 : location.port;
errorReporter.reportTLSError(transportSecurityInfo,
location.hostname, port);
},
onAboutCertError: function (browser, elementId, isTopFrame, location, securityInfoAsString) {

View File

@ -210,10 +210,8 @@ const TLS_ERROR_REPORT_TELEMETRY_FAILURE = 7;
var AboutCertErrorListener = {
init(chromeGlobal) {
addMessageListener("AboutCertErrorDetails", this);
addMessageListener("Browser:SSLErrorReportStatus", this);
chromeGlobal.addEventListener("AboutCertErrorLoad", this, false, true);
chromeGlobal.addEventListener("AboutCertErrorSetAutomatic", this, false, true);
chromeGlobal.addEventListener("AboutCertErrorSendReport", this, false, true);
},
get isAboutCertError() {
@ -232,9 +230,6 @@ var AboutCertErrorListener = {
case "AboutCertErrorSetAutomatic":
this.onSetAutomatic(event);
break;
case "AboutCertErrorSendReport":
this.onSendReport();
break;
}
},
@ -247,9 +242,6 @@ var AboutCertErrorListener = {
case "AboutCertErrorDetails":
this.onDetails(msg);
break;
case "Browser:SSLErrorReportStatus":
this.onReportStatus(msg);
break;
}
},
@ -258,6 +250,11 @@ var AboutCertErrorListener = {
let ownerDoc = originalTarget.ownerDocument;
ClickEventHandler.onAboutCertError(originalTarget, ownerDoc);
// Set up the TLS Error Reporting UI - reports are sent automatically
// (from nsHttpChannel::OnStopRequest) if the user has previously enabled
// automatic sending of reports. The UI ensures that a report is sent
// for the certificate error currently displayed if the user enables it
// here.
let automatic = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic");
content.dispatchEvent(new content.CustomEvent("AboutCertErrorOptions", {
detail: JSON.stringify({
@ -265,10 +262,6 @@ var AboutCertErrorListener = {
automatic,
})
}));
if (automatic) {
this.onSendReport();
}
},
onDetails(msg) {
@ -277,68 +270,31 @@ var AboutCertErrorListener = {
},
onSetAutomatic(event) {
if (event.detail) {
this.onSendReport();
}
sendAsyncMessage("Browser:SetSSLErrorReportAuto", {
automatic: event.detail
});
},
onSendReport() {
let doc = content.document;
let location = doc.location.href;
// if we're enabling reports, send a report for this failure
if (event.detail) {
let doc = content.document;
let location = doc.location.href;
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let serializable = docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
let serializable = docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
let serializedSecurityInfo = serhelper.serializeToString(serializable);
let serializedSecurityInfo = serhelper.serializeToString(serializable);
sendAsyncMessage("Browser:SendSSLErrorReport", {
documentURI: doc.documentURI,
location: {hostname: doc.location.hostname, port: doc.location.port},
securityInfo: serializedSecurityInfo
});
},
onReportStatus(msg) {
let doc = content.document;
if (doc.documentURI != msg.data.documentURI) {
return;
sendAsyncMessage("Browser:SendSSLErrorReport", {
documentURI: doc.documentURI,
location: {hostname: doc.location.hostname, port: doc.location.port},
securityInfo: serializedSecurityInfo
});
}
let reportSendingMsg = doc.getElementById("reportSendingMessage");
let reportSentMsg = doc.getElementById("reportSentMessage");
let retryBtn = doc.getElementById("reportCertificateErrorRetry");
switch (msg.data.reportStatus) {
case "activity":
// Hide the button that was just clicked
retryBtn.style.removeProperty("display");
reportSentMsg.style.removeProperty("display");
reportSendingMsg.style.display = "block";
break;
case "error":
// show the retry button
retryBtn.style.display = "block";
reportSendingMsg.style.removeProperty("display");
sendAsyncMessage("Browser:SSLErrorReportTelemetry",
{reportStatus: TLS_ERROR_REPORT_TELEMETRY_FAILURE});
break;
case "complete":
// Show a success indicator
reportSentMsg.style.display = "block";
reportSendingMsg.style.removeProperty("display");
sendAsyncMessage("Browser:SSLErrorReportTelemetry",
{reportStatus: TLS_ERROR_REPORT_TELEMETRY_SUCCESS});
break;
}
}
},
};
AboutCertErrorListener.init(this);
@ -348,8 +304,6 @@ var AboutNetErrorListener = {
init: function(chromeGlobal) {
chromeGlobal.addEventListener('AboutNetErrorLoad', this, false, true);
chromeGlobal.addEventListener('AboutNetErrorSetAutomatic', this, false, true);
chromeGlobal.addEventListener('AboutNetErrorSendReport', this, false, true);
chromeGlobal.addEventListener('AboutNetErrorUIExpanded', this, false, true);
chromeGlobal.addEventListener('AboutNetErrorOverride', this, false, true);
},
@ -369,13 +323,6 @@ var AboutNetErrorListener = {
case "AboutNetErrorSetAutomatic":
this.onSetAutomatic(aEvent);
break;
case "AboutNetErrorSendReport":
this.onSendReport(aEvent);
break;
case "AboutNetErrorUIExpanded":
sendAsyncMessage("Browser:SSLErrorReportTelemetry",
{reportStatus: TLS_ERROR_REPORT_TELEMETRY_EXPANDED});
break;
case "AboutNetErrorOverride":
this.onOverride(aEvent);
break;
@ -385,91 +332,46 @@ var AboutNetErrorListener = {
onPageLoad: function(evt) {
let automatic = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic");
content.dispatchEvent(new content.CustomEvent("AboutNetErrorOptions", {
detail: JSON.stringify({
enabled: Services.prefs.getBoolPref("security.ssl.errorReporting.enabled"),
automatic: automatic
})
}
));
detail: JSON.stringify({
enabled: Services.prefs.getBoolPref("security.ssl.errorReporting.enabled"),
automatic: automatic
})
}));
sendAsyncMessage("Browser:SSLErrorReportTelemetry",
{reportStatus: TLS_ERROR_REPORT_TELEMETRY_UI_SHOWN});
if (automatic) {
this.onSendReport(evt);
}
// hide parts of the UI we don't need yet
let contentDoc = content.document;
let reportSendingMsg = contentDoc.getElementById("reportSendingMessage");
let reportSentMsg = contentDoc.getElementById("reportSentMessage");
let retryBtn = contentDoc.getElementById("reportCertificateErrorRetry");
reportSendingMsg.style.display = "none";
reportSentMsg.style.display = "none";
retryBtn.style.display = "none";
},
onSetAutomatic: function(evt) {
sendAsyncMessage("Browser:SetSSLErrorReportAuto", {
automatic: evt.detail
automatic: evt.detail
});
// if we're enabling reports, send a report for this failure
if (evt.detail) {
let contentDoc = content.document;
let location = contentDoc.location.href;
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let serializable = docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
let serializedSecurityInfo = serhelper.serializeToString(serializable);
sendAsyncMessage("Browser:SendSSLErrorReport", {
documentURI: contentDoc.documentURI,
location: {
hostname: contentDoc.location.hostname,
port: contentDoc.location.port
},
securityInfo: serializedSecurityInfo
});
},
onSendReport: function(evt) {
let contentDoc = content.document;
let reportSendingMsg = contentDoc.getElementById("reportSendingMessage");
let reportSentMsg = contentDoc.getElementById("reportSentMessage");
let retryBtn = contentDoc.getElementById("reportCertificateErrorRetry");
addMessageListener("Browser:SSLErrorReportStatus", function(message) {
// show and hide bits - but only if this is a message for the right
// document - we'll compare on document URI
if (contentDoc.documentURI === message.data.documentURI) {
switch(message.data.reportStatus) {
case "activity":
// Hide the button that was just clicked
retryBtn.style.display = "none";
reportSentMsg.style.display = "none";
reportSendingMsg.style.removeProperty("display");
break;
case "error":
// show the retry button
retryBtn.style.removeProperty("display");
reportSendingMsg.style.display = "none";
sendAsyncMessage("Browser:SSLErrorReportTelemetry",
{reportStatus: TLS_ERROR_REPORT_TELEMETRY_FAILURE});
break;
case "complete":
// Show a success indicator
reportSentMsg.style.removeProperty("display");
reportSendingMsg.style.display = "none";
sendAsyncMessage("Browser:SSLErrorReportTelemetry",
{reportStatus: TLS_ERROR_REPORT_TELEMETRY_SUCCESS});
break;
}
}
});
let location = contentDoc.location.href;
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let serializable = docShell.failedChannel.securityInfo
.QueryInterface(Ci.nsITransportSecurityInfo)
.QueryInterface(Ci.nsISerializable);
let serializedSecurityInfo = serhelper.serializeToString(serializable);
sendAsyncMessage("Browser:SendSSLErrorReport", {
documentURI: contentDoc.documentURI,
location: {
hostname: contentDoc.location.hostname,
port: contentDoc.location.port
},
securityInfo: serializedSecurityInfo
});
}
},
onOverride: function(evt) {

View File

@ -28,13 +28,12 @@ registerCleanupFunction(() => {
add_task(function* test_send_report_neterror() {
yield testSendReportAutomatically(URL_BAD_CHAIN, "succeed", "neterror");
yield testSendReportAutomatically(URL_NO_CERT, "nocert", "neterror");
yield testSendReportFailRetry(URL_NO_CERT, "nocert", "neterror");
yield testSetAutomatic(URL_NO_CERT, "nocert", "neterror");
});
add_task(function* test_send_report_certerror() {
yield testSendReportAutomatically(URL_BAD_CERT, "badcert", "certerror");
yield testSendReportFailRetry(URL_BAD_CERT, "badcert", "certerror");
yield testSetAutomatic(URL_BAD_CERT, "badcert", "certerror");
});
@ -65,10 +64,11 @@ function* testSendReportAutomatically(testURL, suffix, errorURISuffix) {
let browser = tab.linkedBrowser;
// Load the page and wait for the error report submission.
let promiseReport = createErrorReportPromise(browser);
let promiseStatus = createReportResponseStatusPromise(URL_REPORTS + suffix);
browser.loadURI(testURL);
yield promiseReport;
ok(true, "SSL error report submitted successfully");
ok(!isErrorStatus(yield promiseStatus),
"SSL error report submitted successfully");
// Check that we loaded the right error page.
yield checkErrorPage(browser, errorURISuffix);
@ -78,30 +78,6 @@ function* testSendReportAutomatically(testURL, suffix, errorURISuffix) {
cleanup();
};
function* testSendReportFailRetry(testURL, suffix, errorURISuffix) {
try {
yield testSendReportAutomatically(testURL, "error", errorURISuffix);
ok(false, "sending a report should have failed");
} catch (err) {
ok(err, "saw a failure notification");
}
Services.prefs.setCharPref(PREF_REPORT_URL, URL_REPORTS + suffix);
let browser = gBrowser.selectedBrowser;
let promiseReport = createErrorReportPromise(browser);
let promiseRetry = ContentTask.spawn(browser, null, function* () {
content.document.getElementById("reportCertificateErrorRetry").click();
});
yield Promise.all([promiseReport, promiseRetry]);
ok(true, "SSL error report submitted successfully");
// Cleanup.
gBrowser.removeCurrentTab();
cleanup();
}
function* testSetAutomatic(testURL, suffix, errorURISuffix) {
Services.prefs.setBoolPref(PREF_REPORT_ENABLED, true);
Services.prefs.setBoolPref(PREF_REPORT_AUTOMATIC, false);
@ -118,15 +94,15 @@ function* testSetAutomatic(testURL, suffix, errorURISuffix) {
// Check that we loaded the right error page.
yield checkErrorPage(browser, errorURISuffix);
let statusPromise = createReportResponseStatusPromise(URL_REPORTS + suffix);
// Click the checkbox, enable automatic error reports.
let promiseReport = createErrorReportPromise(browser);
yield ContentTask.spawn(browser, null, function* () {
content.document.getElementById("automaticallyReportInFuture").click();
});
// Wait for the error report submission.
yield promiseReport;
ok(true, "SSL error report submitted successfully");
yield statusPromise;
let isAutomaticReportingEnabled = () =>
Services.prefs.getBoolPref(PREF_REPORT_AUTOMATIC);
@ -170,32 +146,22 @@ function* testSendReportDisabled(testURL, errorURISuffix) {
gBrowser.removeTab(tab);
}
function createErrorReportPromise(browser) {
return ContentTask.spawn(browser, null, function* () {
let type = "Browser:SSLErrorReportStatus";
let active = false;
function isErrorStatus(status) {
return status < 200 || status >= 300;
}
yield new Promise((resolve, reject) => {
addMessageListener(type, function onReportStatus(message) {
switch (message.data.reportStatus) {
case "activity":
active = true;
break;
case "complete":
removeMessageListener(type, onReportStatus);
if (active) {
resolve(message.data.reportStatus);
} else {
reject("activity should be seen before success");
}
break;
case "error":
removeMessageListener(type, onReportStatus);
reject("sending the report failed");
break;
}
});
});
// use the observer service to see when a report is sent
function createReportResponseStatusPromise(expectedURI) {
return new Promise(resolve => {
let observer = (subject, topic, data) => {
subject.QueryInterface(Ci.nsIHttpChannel);
let requestURI = subject.URI.spec;
if (requestURI == expectedURI) {
Services.obs.removeObserver(observer, "http-on-examine-response");
resolve(subject.responseStatus);
}
};
Services.obs.addObserver(observer, "http-on-examine-response", false);
});
}

View File

@ -85,7 +85,7 @@ function handleRequest(request, response) {
break;
default:
response.setStatusLine("1.1", 500, "Server error");
response.write("<html>succeed, nocert or error expected</html>");
response.write("<html>succeed, nocert or error expected (got " + request.queryString + ")</html>");
break;
}
}

View File

@ -36,6 +36,3 @@ you know there's a good reason why this site doesn't use trusted identification.
<!ENTITY certerror.copyToClipboard.label "Copy text to clipboard">
<!ENTITY errorReporting.automatic "Report errors like this to help Mozilla identify misconfigured sites">
<!ENTITY errorReporting.sending "Sending report">
<!ENTITY errorReporting.sent "Report sent">
<!ENTITY errorReporting.tryAgain "Try again">

View File

@ -206,9 +206,6 @@ functionality specific to firefox. -->
<!ENTITY errorReporting.automatic2 "Report errors like this to help Mozilla identify and block malicious sites">
<!ENTITY errorReporting.learnMore "Learn more…">
<!ENTITY errorReporting.sending "Sending report">
<!ENTITY errorReporting.sent "Report sent">
<!ENTITY errorReporting.tryAgain "Try again">
<!ENTITY remoteXUL.title "Remote XUL">
<!ENTITY remoteXUL.longDesc "<p><ul><li>Please contact the website owners to inform them of this problem.</li></ul></p>">

View File

@ -19,6 +19,8 @@
#include "nsICaptivePortalService.h"
#include "nsICryptoHash.h"
#include "nsINetworkInterceptController.h"
#include "nsINSSErrorsService.h"
#include "nsISecurityReporter.h"
#include "nsIStringBundle.h"
#include "nsIStreamListenerTee.h"
#include "nsISeekableStream.h"
@ -1323,6 +1325,56 @@ nsHttpChannel::ProcessSecurityHeaders()
return NS_OK;
}
/**
* Decide whether or not to send a security report and, if so, give the
* SecurityReporter the information required to send such a report.
*/
void
nsHttpChannel::ProcessSecurityReport(nsresult status) {
uint32_t errorClass;
nsCOMPtr<nsINSSErrorsService> errSvc =
do_GetService("@mozilla.org/nss_errors_service;1");
// getErrorClass will throw a generic NS_ERROR_FAILURE if the error code is
// not in the set of errors covered by the NSS errors service.
nsresult rv = errSvc->GetErrorClass(status, &errorClass);
if (!NS_SUCCEEDED(rv)) {
return;
}
// if the content was not loaded succesfully and we have security info,
// send a TLS error report - we must do this early as other parts of
// OnStopRequest can return early
bool reportingEnabled =
Preferences::GetBool("security.ssl.errorReporting.enabled");
bool reportingAutomatic =
Preferences::GetBool("security.ssl.errorReporting.automatic");
if (!mSecurityInfo || !reportingEnabled || !reportingAutomatic) {
return;
}
nsCOMPtr<nsITransportSecurityInfo> secInfo =
do_QueryInterface(mSecurityInfo);
nsCOMPtr<nsISecurityReporter> errorReporter =
do_GetService("@mozilla.org/securityreporter;1");
if (!secInfo || !mURI) {
return;
}
nsAutoCString hostStr;
int32_t port;
rv = mURI->GetHost(hostStr);
if (!NS_SUCCEEDED(rv)) {
return;
}
rv = mURI->GetPort(&port);
if (NS_SUCCEEDED(rv)) {
errorReporter->ReportTLSError(secInfo, hostStr, port);
}
}
bool
nsHttpChannel::IsHTTPS()
{
@ -5765,6 +5817,13 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
LOG(("nsHttpChannel::OnStopRequest [this=%p request=%p status=%x]\n",
this, request, status));
MOZ_ASSERT(NS_IsMainThread(),
"OnStopRequest should only be called from the main thread");
if (NS_FAILED(status)) {
ProcessSecurityReport(status);
}
if (mTimingEnabled && request == mCachePump) {
mCacheReadEnd = TimeStamp::Now();
}

View File

@ -365,6 +365,11 @@ private:
*/
nsresult ProcessSecurityHeaders();
/**
* A function that will, if the feature is enabled, send security reports.
*/
void ProcessSecurityReport(nsresult status);
/**
* A function to process a single security header (STS or PKP), assumes
* some basic sanity checks have been applied to the channel. Called