Bug 1342178 - Pass origin attributes to isSecureURI in devtools and browser. r=keeler,past
MozReview-Commit-ID: HIOYH8iUUkO
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3019,17 +3019,18 @@ var BrowserOnClick = {
}
},
receiveMessage(msg) {
switch (msg.name) {
case "Browser:CertExceptionError":
this.onCertError(msg.target, msg.data.elementId,
msg.data.isTopFrame, msg.data.location,
- msg.data.securityInfoAsString);
+ msg.data.securityInfoAsString,
+ msg.data.originAttributesAsString);
break;
case "Browser:OpenCaptivePortalPage":
CaptivePortalWatcher.ensureCaptivePortalTab();
break;
case "Browser:SiteBlockedError":
this.onAboutBlocked(msg.data.elementId, msg.data.reason,
msg.data.isTopFrame, msg.data.location,
msg.data.blockedInfo);
@@ -3083,17 +3084,18 @@ var BrowserOnClick = {
transportSecurityInfo.QueryInterface(Ci.nsITransportSecurityInfo)
let errorReporter = Cc["@mozilla.org/securityreporter;1"]
.getService(Ci.nsISecurityReporter);
errorReporter.reportTLSError(transportSecurityInfo,
uri.host, uri.port);
},
- onCertError(browser, elementId, isTopFrame, location, securityInfoAsString) {
+ onCertError(browser, elementId, isTopFrame, location, securityInfoAsString,
+ originAttributesAsString) {
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
let securityInfo;
switch (elementId) {
case "exceptionDialogButton":
if (isTopFrame) {
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_CLICK_ADD_EXCEPTION);
}
@@ -3133,29 +3135,31 @@ var BrowserOnClick = {
case "advancedButton":
if (isTopFrame) {
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_UNDERSTAND_RISKS);
}
securityInfo = getSecurityInfo(securityInfoAsString);
let errorInfo = getDetailedCertErrorInfo(location,
- securityInfo);
+ securityInfo,
+ JSON.parse(originAttributesAsString));
browser.messageManager.sendAsyncMessage( "CertErrorDetails", {
code: securityInfo.errorCode,
info: errorInfo
});
break;
case "copyToClipboard":
const gClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper);
securityInfo = getSecurityInfo(securityInfoAsString);
let detailedInfo = getDetailedCertErrorInfo(location,
- securityInfo);
+ securityInfo,
+ JSON.parse(originAttributesAsString));
gClipboardHelper.copyString(detailedInfo);
break;
}
},
onAboutBlocked(elementId, reason, isTopFrame, location, blockedInfo) {
// Depending on what page we are displaying here (malware/phishing/unwanted)
@@ -3410,17 +3414,17 @@ function getSecurityInfo(securityInfoAsS
return securityInfo;
}
/**
* Returns a string with detailed information about the certificate validation
* failure from the specified URI that can be used to send a report.
*/
-function getDetailedCertErrorInfo(location, securityInfo) {
+function getDetailedCertErrorInfo(location, securityInfo, originAttributes) {
if (!securityInfo)
return "";
let certErrorDetails = location;
let code = securityInfo.errorCode;
let errors = Cc["@mozilla.org/nss_errors_service;1"]
.getService(Ci.nsINSSErrorsService);
@@ -3431,18 +3435,18 @@ function getDetailedCertErrorInfo(locati
// SiteSecurityService uses different storage if the channel is
// private. Thus we must give isSecureURI correct flags or we
// might get incorrect results.
let flags = PrivateBrowsingUtils.isWindowPrivate(window) ?
Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
let uri = Services.io.newURI(location);
- let hasHSTS = sss.isSecureURI(sss.HEADER_HSTS, uri, flags);
- let hasHPKP = sss.isSecureURI(sss.HEADER_HPKP, uri, flags);
+ let hasHSTS = sss.isSecureURI(sss.HEADER_HSTS, uri, flags, originAttributes);
+ let hasHPKP = sss.isSecureURI(sss.HEADER_HPKP, uri, flags, originAttributes);
certErrorDetails += "\r\n\r\n" +
gNavigatorBundle.getFormattedString("certErrorDetailsHSTS.label",
[hasHSTS]);
certErrorDetails += "\r\n" +
gNavigatorBundle.getFormattedString("certErrorDetailsKeyPinning.label",
[hasHPKP]);
let certChain = "";
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -288,16 +288,24 @@ function getSiteBlockedErrorDetails(docS
}
addMessageListener("DeceptiveBlockedDetails", (message) => {
sendAsyncMessage("DeceptiveBlockedDetails:Result", {
blockedInfo: getSiteBlockedErrorDetails(docShell),
});
});
+function getSerializedOriginAttributes(docShell) {
+ let originAttributes = {};
+ if (docShell.failedChannel) {
+ originAttributes = docShell.failedChannel.loadInfo.originAttributes;
+ }
+ return JSON.stringify(originAttributes);
+}
+
var AboutNetAndCertErrorListener = {
init(chromeGlobal) {
addMessageListener("CertErrorDetails", this);
addMessageListener("Browser:CaptivePortalFreed", this);
chromeGlobal.addEventListener("AboutNetErrorLoad", this, false, true);
chromeGlobal.addEventListener("AboutNetErrorOpenCaptivePortal", this, false, true);
chromeGlobal.addEventListener("AboutNetErrorSetAutomatic", this, false, true);
chromeGlobal.addEventListener("AboutNetErrorResetPreferences", this, false, true);
@@ -596,16 +604,17 @@ var ClickEventHandler = {
let docShell = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
sendAsyncMessage("Browser:CertExceptionError", {
location: ownerDoc.location.href,
elementId: targetElement.getAttribute("id"),
isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView),
securityInfoAsString: getSerializedSecurityInfo(docShell),
+ originAttributesAsString: getSerializedOriginAttributes(docShell),
});
},
onAboutBlocked(targetElement, ownerDoc) {
var reason = "phishing";
if (/e=malwareBlocked/.test(ownerDoc.documentURI)) {
reason = "malware";
} else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) {
--- a/browser/base/content/test/general/browser_aboutCertError.js
+++ b/browser/base/content/test/general/browser_aboutCertError.js
@@ -254,20 +254,23 @@ add_task(function* checkAdvancedDetails(
let text = doc.getElementById("certificateErrorText");
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);
+ let originAttributes = docShell.failedChannel.loadInfo.originAttributes;
+ let serializedOriginAttributes = JSON.stringify(originAttributes);
return {
divDisplay: content.getComputedStyle(div).display,
text: text.textContent,
- securityInfoAsString: serializedSecurityInfo
+ securityInfoAsString: serializedSecurityInfo,
+ originAttributesAsString: serializedOriginAttributes,
};
});
isnot(message.divDisplay, "none", "Debug information is visible");
ok(message.text.includes(BAD_CERT), "Correct URL found");
ok(message.text.includes("Certificate has expired"),
"Correct error message found");
ok(message.text.includes("HTTP Strict Transport Security: false"),
"Correct HSTS value found");
@@ -323,20 +326,23 @@ add_task(function* checkAdvancedDetailsF
let text = doc.getElementById("certificateErrorText");
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);
+ let originAttributes = docShell.failedChannel.loadInfo.originAttributes;
+ let serializedOriginAttributes = JSON.stringify(originAttributes);
return {
divDisplay: content.getComputedStyle(div).display,
text: text.textContent,
- securityInfoAsString: serializedSecurityInfo
+ securityInfoAsString: serializedSecurityInfo,
+ originAttributesAsString: serializedOriginAttributes,
};
});
isnot(message.divDisplay, "none", "Debug information is visible");
ok(message.text.includes(badStsUri.spec), "Correct URL found");
ok(message.text.includes("requested domain name does not match the server\u2019s certificate"),
"Correct error message found");
ok(message.text.includes("HTTP Strict Transport Security: false"),
"Correct HSTS value found");
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -8935,20 +8935,30 @@ return /******/ (function(modules) { //
// SiteSecurityService uses different storage if the channel is
// private. Thus we must give isSecureHost correct flags or we
// might get incorrect results.
let flags = (httpActivity.private) ?
Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
- let host = httpActivity.hostname;
-
- info.hsts = sss.isSecureHost(sss.HEADER_HSTS, host, flags);
- info.hpkp = sss.isSecureHost(sss.HEADER_HPKP, host, flags);
+ if (!uri) {
+ // isSecureURI only cares about the host, not the scheme.
+ let host = httpActivity.hostname;
+ uri = Services.io.newURI("https://" + host);
+ }
+
+ let originAttributes = {};
+ if (httpActivity.channel) {
+ originAttributes = httpActivity.channel.loadInfo.originAttributes;
+ }
+ info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags,
+ originAttributes);
+ info.hpkp = sss.isSecureURI(sss.HEADER_HPKP, uri, flags,
+ originAttributes);
} else {
DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo",
"Could not get HSTS/HPKP status as hostname is not available.");
info.hsts = false;
info.hpkp = false;
}
} else {
--- a/devtools/shared/webconsole/network-helper.js
+++ b/devtools/shared/webconsole/network-helper.js
@@ -639,18 +639,24 @@ var NetworkHelper = {
Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
if (!uri) {
// isSecureURI only cares about the host, not the scheme.
let host = httpActivity.hostname;
uri = Services.io.newURI("https://" + host);
}
- info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags);
- info.hpkp = sss.isSecureURI(sss.HEADER_HPKP, uri, flags);
+ let originAttributes = {};
+ if (httpActivity.channel) {
+ originAttributes = httpActivity.channel.loadInfo.originAttributes;
+ }
+ info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags,
+ originAttributes);
+ info.hpkp = sss.isSecureURI(sss.HEADER_HPKP, uri, flags,
+ originAttributes);
} else {
DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo",
"Could not get HSTS/HPKP status as hostname is not available.");
info.hsts = false;
info.hpkp = false;
}
} else {
// The connection failed.