Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1797)

Unified Diff: Source/devtools/front_end/security/SecurityPanel.js

Issue 1301833003: Add origin views to the Security panel. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Use div and flex instead of table. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/devtools/front_end/security/SecurityPanel.js
diff --git a/Source/devtools/front_end/security/SecurityPanel.js b/Source/devtools/front_end/security/SecurityPanel.js
index 177a57d1c5e1420b2a55a6b601dc58f8ea2038bc..840003791410a07ac2fca88eef531c6922402da3 100644
--- a/Source/devtools/front_end/security/SecurityPanel.js
+++ b/Source/devtools/front_end/security/SecurityPanel.js
@@ -7,7 +7,8 @@
* @extends {WebInspector.PanelWithSidebar}
* @implements {WebInspector.TargetManager.Observer}
*/
-WebInspector.SecurityPanel = function() {
+WebInspector.SecurityPanel = function()
+{
WebInspector.PanelWithSidebar.call(this, "security");
this.registerRequiredCSS("security/securityPanel.css");
this.registerRequiredCSS("security/lockIcon.css");
@@ -15,24 +16,30 @@ WebInspector.SecurityPanel = function() {
var sidebarTree = new TreeOutlineInShadow();
sidebarTree.element.classList.add("sidebar-tree");
this.panelSidebarElement().appendChild(sidebarTree.element);
+ sidebarTree.registerRequiredCSS("security/sidebar.css");
sidebarTree.registerRequiredCSS("security/lockIcon.css");
this.setDefaultFocusedElement(sidebarTree.element);
this._sidebarMainViewElement = new WebInspector.SecurityMainViewSidebarTreeElement(this);
sidebarTree.appendChild(this._sidebarMainViewElement);
+ // TODO(lgarron): Add a section for the main origin. (https://crbug.com/523586)
+ this._sidebarOriginSection = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("Origins"));
+ this._sidebarOriginSection.listItemElement.classList.add("security-sidebar-origins");
+ sidebarTree.appendChild(this._sidebarOriginSection);
+
this._mainView = new WebInspector.SecurityMainView();
- this.showMainView();
/** @type {!Map<string, !{securityState: !SecurityAgent.SecurityState, securityDetails: ?NetworkAgent.SecurityDetails}>} */
dgozman 2015/08/25 20:21:51 You store the originView here. Update JSDoc.
lgarron 2015/08/25 21:03:07 Good point. I've created a separate WebInspector.S
this._origins = new Map();
- WebInspector.targetManager.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._clear, this);
- WebInspector.targetManager.addEventListener(WebInspector.ResourceTreeModel.EventTypes.WillReloadPage, this._clear, this);
- WebInspector.targetManager.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._clear, this);
+ // TODO(lgarron): add event listeners to call _clear() once we figure out how to clear the panel properly (https://crbug.com/522762).
WebInspector.targetManager.observeTargets(this);
}
+/** @typedef {string} */
+WebInspector.SecurityPanel.Origin;
+
WebInspector.SecurityPanel.prototype = {
/**
@@ -61,6 +68,25 @@ WebInspector.SecurityPanel.prototype = {
},
/**
+ * @param {!WebInspector.SecurityPanel.Origin} origin
+ */
+ showOrigin: function(origin)
+ {
+ var originData = this._origins.get(origin);
+ if (!originData.originView)
+ originData.originView = new WebInspector.SecurityOriginView(this, origin, originData.securityState, originData.securityDetails);
+
+ this._setVisibleView(originData.originView);
+ },
+
+ wasShown: function()
+ {
+ WebInspector.Panel.prototype.wasShown.call(this);
+ if (!this._visibleView)
+ this._sidebarMainViewElement.select();
+ },
+
+ /**
* @param {!WebInspector.VBox} view
*/
_setVisibleView: function(view)
@@ -88,15 +114,27 @@ WebInspector.SecurityPanel.prototype = {
if (this._origins.has(origin)) {
var originData = this._origins.get(origin);
- originData.securityState = this._securityStateMin(originData.securityState, securityState);
+ var oldSecurityState = originData.securityState;
+ originData.securityState = this._securityStateMin(oldSecurityState, securityState);
+ if (oldSecurityState != originData.securityState) {
+ originData.sidebarElement.setSecurityState(securityState);
+ if (originData.originView)
+ originData.originView.setSecurityState(securityState);
+ }
} else {
- // TODO(lgarron): Store a (deduplicated) list of different security details we have seen.
+ // TODO(lgarron): Store a (deduplicated) list of different security details we have seen. https://crbug.com/503170
var originData = {};
originData.securityState = securityState;
if (data.securityDetails)
originData.securityDetails = data.securityDetails;
this._origins.set(origin, originData);
+
+ originData.sidebarElement = new WebInspector.SecurityOriginViewSidebarTreeElement(this, origin);
+ this._sidebarOriginSection.appendChild(originData.sidebarElement);
+ originData.sidebarElement.setSecurityState(securityState);
+
+ // Don't construct the origin view yet (let it happen lazily).
}
},
@@ -148,6 +186,8 @@ WebInspector.SecurityPanel.prototype = {
_clear: function()
{
this._updateSecurityState(SecurityAgent.SecurityState.Unknown, []);
+ this._sidebarMainViewElement.select();
+ this._sidebarOriginSection.removeChildren();
this._origins.clear();
},
@@ -172,8 +212,7 @@ WebInspector.SecurityPanel._instance = function()
WebInspector.SecurityMainViewSidebarTreeElement = function(panel)
{
this._panel = panel;
- this.small = true;
- WebInspector.SidebarTreeElement.call(this, "security-sidebar-tree-item", WebInspector.UIString("Overview"));
+ WebInspector.SidebarTreeElement.call(this, "security-main-view-sidebar-tree-item", WebInspector.UIString("Overview"));
this.iconElement.classList.add("lock-icon");
}
@@ -188,9 +227,10 @@ WebInspector.SecurityMainViewSidebarTreeElement.prototype = {
*/
setSecurityState: function(newSecurityState)
{
- for (var className of this.iconElement.classList)
- if (className.indexOf("lock-icon-") === 0)
+ for (var className of Array.prototype.slice.call(this.iconElement.classList)) {
+ if (className.startsWith("lock-icon-"))
this.iconElement.classList.remove(className);
+ }
this.iconElement.classList.add("lock-icon-" + newSecurityState);
},
@@ -210,6 +250,48 @@ WebInspector.SecurityMainViewSidebarTreeElement.prototype = {
/**
* @constructor
+ * @extends {WebInspector.SidebarTreeElement}
+ * @param {!WebInspector.SecurityPanel} panel
+ * @param {!WebInspector.SecurityPanel.Origin} origin
+ */
+WebInspector.SecurityOriginViewSidebarTreeElement = function(panel, origin)
+{
+ this._panel = panel;
+ this._origin = origin;
+ this.small = true;
+ WebInspector.SidebarTreeElement.call(this, "security-sidebar-tree-item", origin);
+ this.iconElement.classList.add("security-property");
+}
+
+WebInspector.SecurityOriginViewSidebarTreeElement.prototype = {
+ /**
+ * @override
+ * @return {boolean}
+ */
+ onselect: function()
+ {
+ this._panel.showOrigin(this._origin);
+ return true;
+ },
+
+ /**
+ * @param {!SecurityAgent.SecurityState} newSecurityState
+ */
+ setSecurityState: function(newSecurityState)
+ {
+ for (var className of Array.prototype.slice.call(this.iconElement.classList)) {
+ if (className.startsWith("security-property-"))
+ this.iconElement.classList.remove(className);
+ }
+
+ this.iconElement.classList.add("security-property-" + newSecurityState);
+ },
+
+ __proto__: WebInspector.SidebarTreeElement.prototype
+}
+
+/**
+ * @constructor
* @implements {WebInspector.PanelFactory}
*/
WebInspector.SecurityPanelFactory = function()
@@ -257,8 +339,8 @@ WebInspector.SecurityMainView.prototype = {
var explanationLockIcon = explanationDiv.createChild("div", "lock-icon");
explanationLockIcon.classList.add("lock-icon-" + explanation.securityState);
- explanationDiv.createChild("div", "explanation-title").textContent = explanation.summary;
- explanationDiv.createChild("div", "explanation-text").textContent = explanation.description;
+ explanationDiv.createChild("div", "explanation-title").textContent = WebInspector.UIString(explanation.summary);
+ explanationDiv.createChild("div", "explanation-text").textContent = WebInspector.UIString(explanation.description);
},
/**
@@ -283,3 +365,146 @@ WebInspector.SecurityMainView.prototype = {
__proto__: WebInspector.VBox.prototype
}
+
+/**
+ * @constructor
+ * @extends {WebInspector.VBox}
+ * @param {!WebInspector.SecurityPanel} panel
+ * @param {!WebInspector.SecurityPanel.Origin} origin
+ * @param {!SecurityAgent.SecurityState} securityState
+ * @param {?NetworkAgent.SecurityDetails} securityDetails
+ */
+WebInspector.SecurityOriginView = function(panel, origin, securityState, securityDetails)
+{
+ this._panel = panel;
+ WebInspector.VBox.call(this);
+ this.setMinimumSize(200, 100);
+
+ this.element.classList.add("security-origin-view");
+ this.registerRequiredCSS("security/originView.css");
+ this.registerRequiredCSS("security/lockIcon.css");
+
+ var titleSection = this.element.createChild("div", "origin-view-section title-section");
+ titleSection.createChild("div", "origin-view-title").textContent = WebInspector.UIString("Origin");
+ var originDisplay = titleSection.createChild("div", "origin-display");
+ this._originLockIcon = originDisplay.createChild("span", "security-property");
+ this._originLockIcon.classList.add("security-property-" + securityState);
+ // TODO(lgarron): Highlight the origin scheme. https://crbug.com/523589
+ originDisplay.createChild("span", "origin").textContent = origin;
+
+ if (securityDetails && securityDetails.certificateDetails) {
+ var connectionSection = this.element.createChild("div", "origin-view-section");
+ connectionSection.createChild("div", "origin-view-section-title").textContent = WebInspector.UIString("Connection");
+
+ var table = new WebInspector.SecurityDetailsTable();
+ connectionSection.appendChild(table.element());
+ table.addRow("Protocol", securityDetails.protocol);
+ table.addRow("Key Exchange", securityDetails.keyExchange);
+ table.addRow("Cipher Suite", securityDetails.cipher + (securityDetails.mac ? " with " + securityDetails.mac : ""));
+ }
+
+ if (securityDetails) {
+ var certificateSection = this.element.createChild("div", "origin-view-section");
+ certificateSection.createChild("div", "origin-view-section-title").textContent = WebInspector.UIString("Certificate");
+
+ var sanDiv = this._createSanDiv(securityDetails);
+ var validFromString = new Date(1000 * securityDetails.certificateDetails.validFrom).toUTCString();
+ var validUntilString = new Date(1000 * securityDetails.certificateDetails.validTo).toUTCString();
+
+ var table = new WebInspector.SecurityDetailsTable();
+ certificateSection.appendChild(table.element());
+ table.addRow("Subject", securityDetails.certificateDetails.subject.name);
+ table.addRow("SAN", sanDiv);
+ table.addRow("Valid From", validFromString);
+ table.addRow("Valid Until", validUntilString);
+ table.addRow("Issuer", securityDetails.certificateDetails.issuer);
+ // TODO(lgarron): Make SCT status available in certificate details and show it here.
+
+ // TODO(lgarron): Implement a link to get certificateDetails. https://crbug.com/506468
+
+ var noteSection = this.element.createChild("div", "origin-view-section");
+ noteSection.createChild("div", "origin-view-section-title").textContent = WebInspector.UIString("Development Note");
+ // TODO(lgarron): Fix the issue and then remove this section. See comment in _onResponseReceivedSecurityDetails
+ noteSection.createChild("div").textContent = WebInspector.UIString("At the moment, this view only shows security details from the first connection made to %s", origin);
+ }
+
+ if (!securityDetails) {
+ var notSecureSection = this.element.createChild("div", "origin-view-section");
+ notSecureSection.createChild("div", "origin-view-section-title").textContent = WebInspector.UIString("Not Secure");
+ notSecureSection.createChild("div").textContent = WebInspector.UIString("Your connection to this origin is not secure.");
+ }
+}
+
+WebInspector.SecurityOriginView.prototype = {
+
+ /**
+ * @param {!NetworkAgent.SecurityDetails} securityDetails
+ * *return {!Element}
+ */
+ _createSanDiv: function(securityDetails)
+ {
+ // TODO(lgarron): Truncate the display of SAN entries and add a button to toggle the full list. https://crbug.com/523591
+ var sanDiv = createElement("div");
+ var sanList = securityDetails.certificateDetails.subject.sanDnsNames.concat(securityDetails.certificateDetails.subject.sanIpAddresses);
+ if (sanList.length === 0) {
+ sanDiv.textContent = WebInspector.UIString("(N/A)");
+ } else {
+ for (var sanEntry of sanList) {
+ var span = sanDiv.createChild("span", "san-entry");
+ span.textContent = WebInspector.UIString(sanEntry);
+ }
+ }
+ return sanDiv;
+ },
+
+ /**
+ * @param {!SecurityAgent.SecurityState} newSecurityState
+ */
+ setSecurityState: function(newSecurityState)
+ {
+ for (var className of Array.prototype.slice.call(this._originLockIcon.classList)) {
+ if (className.startsWith("security-property-"))
+ this._originLockIcon.classList.remove(className);
+ }
+
+ this._originLockIcon.classList.add("security-property-" + newSecurityState);
+ },
+
+ __proto__: WebInspector.VBox.prototype
+}
+
+/**
+ * @constructor
+ */
+WebInspector.SecurityDetailsTable = function() {
dgozman 2015/08/25 20:21:51 nit: { on next line
lgarron 2015/08/25 21:03:07 Done.
+ this._element = createElement("table");
+ this._element.classList.add("details-table");
+}
+
+WebInspector.SecurityDetailsTable.prototype = {
+
+ /**
+ * @return: {!Element}
+ */
+ element: function() {
dgozman 2015/08/25 20:21:51 nit: { on next line
lgarron 2015/08/25 21:03:07 Done.
+ return this._element;
+ },
+
+ /**
+ * @param {string} key
+ * @param {string|!HTMLDivElement} value
+ */
+ addRow: function(key, value)
+ {
+ var row = this._element.createChild("div", "details-table-row");
+ row.createChild("div").textContent = WebInspector.UIString(key);
+
+ var valueDiv = row.createChild("div");
+ if (value instanceof HTMLDivElement) {
+ valueDiv.appendChild(value);
+ } else {
+ valueDiv.textContent = value;
+ }
+ },
dgozman 2015/08/25 20:21:51 nit: extra comma
lgarron 2015/08/25 21:03:07 Done.
+}
+
« no previous file with comments | « Source/devtools/front_end/Images/securityPropertyWarning.svg ('k') | Source/devtools/front_end/security/lockIcon.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698