Files

177 lines
5.6 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { DOM, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const PropertiesView = createFactory(require("./properties-view"));
const { L10N } = require("../../l10n");
const { getUrlHost } = require("../../request-utils");
const { getSelectedRequest } = require("../../selectors/index");
const { div, input, span } = DOM;
/*
* Security panel component
* If the site is being served over HTTPS, you get an extra tab labeled "Security".
* This contains details about the secure connection used including the protocol,
* the cipher suite, and certificate details
*/
function SecurityPanel({
securityInfo,
url,
}) {
if (!securityInfo || !url) {
return div();
}
const notAvailable = L10N.getStr("netmonitor.security.notAvailable");
let object;
if ((securityInfo.state === "secure" || securityInfo.state === "weak")) {
const { subject, issuer, validity, fingerprint } = securityInfo.cert;
const enabledLabel = L10N.getStr("netmonitor.security.enabled");
const disabledLabel = L10N.getStr("netmonitor.security.disabled");
object = {
[L10N.getStr("netmonitor.security.connection")]: {
[L10N.getStr("netmonitor.security.protocolVersion")]:
securityInfo.protocolVersion || notAvailable,
[L10N.getStr("netmonitor.security.cipherSuite")]:
securityInfo.cipherSuite || notAvailable,
[L10N.getStr("netmonitor.security.keaGroup")]:
securityInfo.keaGroupName || notAvailable,
[L10N.getStr("netmonitor.security.signatureScheme")]:
securityInfo.signatureSchemeName || notAvailable,
},
[L10N.getFormatStr("netmonitor.security.hostHeader", getUrlHost(url))]: {
[L10N.getStr("netmonitor.security.hsts")]:
securityInfo.hsts ? enabledLabel : disabledLabel,
[L10N.getStr("netmonitor.security.hpkp")]:
securityInfo.hpkp ? enabledLabel : disabledLabel,
},
[L10N.getStr("netmonitor.security.certificate")]: {
[L10N.getStr("certmgr.subjectinfo.label")]: {
[L10N.getStr("certmgr.certdetail.cn")]:
subject.commonName || notAvailable,
[L10N.getStr("certmgr.certdetail.o")]:
subject.organization || notAvailable,
[L10N.getStr("certmgr.certdetail.ou")]:
subject.organizationUnit || notAvailable,
},
[L10N.getStr("certmgr.issuerinfo.label")]: {
[L10N.getStr("certmgr.certdetail.cn")]:
issuer.commonName || notAvailable,
[L10N.getStr("certmgr.certdetail.o")]:
issuer.organization || notAvailable,
[L10N.getStr("certmgr.certdetail.ou")]:
issuer.organizationUnit || notAvailable,
},
[L10N.getStr("certmgr.periodofvalidity.label")]: {
[L10N.getStr("certmgr.begins")]:
validity.start || notAvailable,
[L10N.getStr("certmgr.expires")]:
validity.end || notAvailable,
},
[L10N.getStr("certmgr.fingerprints.label")]: {
[L10N.getStr("certmgr.certdetail.sha256fingerprint")]:
fingerprint.sha256 || notAvailable,
[L10N.getStr("certmgr.certdetail.sha1fingerprint")]:
fingerprint.sha1 || notAvailable,
},
},
};
} else {
object = {
[L10N.getStr("netmonitor.security.error")]:
new DOMParser().parseFromString(securityInfo.errorMessage, "text/html")
.body.textContent || notAvailable
};
}
return div({ className: "panel-container" },
PropertiesView({
object,
renderValue: (props) => renderValue(props, securityInfo.weaknessReasons),
enableFilter: false,
expandedNodes: getExpandedNodes(object),
})
);
}
SecurityPanel.displayName = "SecurityPanel";
SecurityPanel.propTypes = {
securityInfo: PropTypes.object,
url: PropTypes.string,
};
function renderValue(props, weaknessReasons = []) {
const { member, value } = props;
// Hide object summary
if (typeof member.value === "object") {
return null;
}
return span({ className: "security-info-value" },
member.name === L10N.getStr("netmonitor.security.error") ?
// Display multiline text for security error
value
:
// Display one line selectable text for security details
input({
className: "textbox-input",
readOnly: "true",
value,
})
,
weaknessReasons.indexOf("cipher") !== -1 &&
member.name === L10N.getStr("netmonitor.security.cipherSuite") ?
// Display an extra warning icon after the cipher suite
div({
id: "security-warning-cipher",
className: "security-warning-icon",
title: L10N.getStr("netmonitor.security.warning.cipher"),
})
:
null
);
}
function getExpandedNodes(object, path = "", level = 0) {
if (typeof object !== "object") {
return null;
}
let expandedNodes = new Set();
for (let prop in object) {
let nodePath = path + "/" + prop;
expandedNodes.add(nodePath);
let nodes = getExpandedNodes(object[prop], nodePath, level + 1);
if (nodes) {
expandedNodes = new Set([...expandedNodes, ...nodes]);
}
}
return expandedNodes;
}
module.exports = connect(
(state) => {
const selectedRequest = getSelectedRequest(state);
if (selectedRequest) {
const { securityInfo, url} = selectedRequest;
return {
securityInfo,
url,
};
}
return {};
}
)(SecurityPanel);