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

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

Issue 1742743002: Add CSP information to Security Panel. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update to cleaner UX. Always shows CSP data, whether on HTTPS page or not. Created 4 years, 9 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: third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
index 2bc3e5f51ccdabe1cbaf2892e73c393dae294821..9e015868b06bbc841af5be6cdc46785b6ebe43a9 100644
--- a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
@@ -44,6 +44,7 @@ WebInspector.SecurityPanel.Origin;
* @property {?NetworkAgent.SecurityDetails} securityDetails - Security details of the origin, if available.
* @property {?Promise<!NetworkAgent.CertificateDetails>} certificateDetailsPromise - Certificate details of the origin. Only available if securityDetails are available.
* @property {?WebInspector.SecurityOriginView} originView - Current SecurityOriginView corresponding to origin.
+ * @property {?WebInspector.CSPParser} cspDetails - Content Security Policy details
*/
WebInspector.SecurityPanel.OriginState;
@@ -180,6 +181,17 @@ WebInspector.SecurityPanel.prototype = {
originState.certificateDetailsPromise = request.target().networkManager.certificateDetailsPromise(securityDetails.certificateId);
}
+ if (Runtime.experiments.isEnabled("cspDetailsInSecurityPanel")) {
+ var cspHeader = request.responseHeaders.filter(header => header.name.toLowerCase().includes("content-security-policy"))[0];
+ if (cspHeader) {
+ originState.cspDetails =
+ WebInspector.CSPParser.buildFromString(
+ cspHeader.value,
+ cspHeader.name.toLowerCase().includes("report-only")
+ );
+ }
+ }
+
this._origins.set(origin, originState);
this._sidebarTree.addOrigin(origin, securityState);
@@ -821,6 +833,125 @@ WebInspector.SecurityOriginView = function(panel, origin, originState)
noInfoSection.createChild("div", "origin-view-section-title").textContent = WebInspector.UIString("No Security Information");
noInfoSection.createChild("div").textContent = WebInspector.UIString("No security details are available for this origin.");
}
+
+ if (Runtime.experiments.isEnabled("cspDetailsInSecurityPanel") && originState.cspDetails) {
+ let contentSecurityPolicySection = this.element.createChild("div", "origin-view-section");
+ contentSecurityPolicySection.createChild("div", "origin-view-section-title").textContent = WebInspector.UIString("Content Security Policy");
+ let toggleButton = createElement("button");
+ toggleButton.textContent = "Collapse All Policies";
+ toggleButton.dataset.showing = true;
+ toggleButton.className = "collapse-policies";
+ contentSecurityPolicySection.appendChild(toggleButton);
+
+ let reportUri = createElement("p");
+ reportUri.innerHTML = `<b>Report URI</b> <span>${originState.cspDetails.reportUri ? originState.cspDetails.reportUri : "Not Set"}</span>`;
+ contentSecurityPolicySection.appendChild(reportUri);
+
+ toggleButton.addEventListener("click", () => {
+ let headings = contentSecurityPolicySection.querySelectorAll(".csp-rule-heading");
+ if (toggleButton.dataset.showing === "true") {
+ Array.prototype.forEach.call(headings, item => {
+ item.closeSection();
+ });
+ toggleButton.textContent = "Show All Policies";
+ toggleButton.dataset.showing = false;
+ } else {
+ Array.prototype.forEach.call(headings, item => {
+ item.showSection();
+ });
+ toggleButton.textContent = "Collapse Policies";
+ toggleButton.dataset.showing = true;
+ }
+ });
+
+ /**
+ * Create the sections for the CSP display.
+ *
+ * @param {!WebInspector.CSPParser.Policy} policy The CSP Policy to create a section for.
+ */
+ function createPolicySection(policy) {
+
+ // Since for some reason a blank policy may get made sometimes.
+ if (!policy.name) {
+ return;
+ }
+
+ /**
+ * Create table row for a CSP Rule
+ * @param {!WebInspector.CSPParser.Rule} rule The rule to create a table entry for.
+ * @return {string}
+ */
+ function createRuleRow(rule) {
+ return `
+ <tr class="csp-rule csp-security-state-${rule.securityState}">
+ <th><span class="lock-icon lock-icon-${rule.securityState}"></span><p>${rule.value}</p></th>
+ <td>
+ <p><b>Security Level</b> <span>${rule.humanReadableSecurityState}</span></p>
+ ${rule.reason ? `<p><b>Reason</b> <span>${rule.reason}</span></p>` : ""}
+ <p><b>Report Only</b> <span>${rule.reportOnly ? "Yes" : "No"}</span></p>
+ </td>
+ </tr>`;
+ }
+ let heading = createElement("h4");
+ heading.dataset.rule = policy.name;
+ heading.className = `csp-rule csp-rule-heading csp-security-state-${policy.securityState}`;
+ heading.textContent = policy.name;
+ heading.innerHTML += `<span class="icon"></span>`;
+ contentSecurityPolicySection.appendChild(heading);
+
+ let policyStateArea = createElement("p");
+ policyStateArea.innerHTML = `<b>Policy state</b> ${policy.humanReadableSecurityState}`;
+ if (policy.securityStateReason) {
+ policyStateArea.innerHTML += `<br><b>Reason</b> ${policy.securityStateReason}`;
+ }
+ contentSecurityPolicySection.appendChild(policyStateArea);
+
+ let table = createElementWithClass("table", `csp-directive csp-rule-list-${policy.name}`);
+ table.innerHTML += `
+ <tbody>
+ ${policy.rules.sort((a, b) => a.value.localeCompare(b.value)).map(createRuleRow).join('')}
+ </tbody>
+ </table>`;
+ contentSecurityPolicySection.appendChild(table);
+
+ /**
+ * @this {Element}
+ */
+ heading.toggleSection = function() {
+ contentSecurityPolicySection
+ .querySelector(`.csp-rule-list-${policy.name}`)
+ .classList
+ .toggle("csp-directive_hidden");
+ this.classList.toggle("directive-is-hidden");
+ };
+ /**
+ * @this {Element}
+ */
+ heading.closeSection = function() {
+ contentSecurityPolicySection
+ .querySelector(`.csp-rule-list-${policy.name}`)
+ .classList
+ .add("csp-directive_hidden");
+ this.classList.add("directive-is-hidden");
+ };
+ /**
+ * @this {Element}
+ */
+ heading.showSection = function () {
+ contentSecurityPolicySection
+ .querySelector(`.csp-rule-list-${policy.name}`)
+ .classList
+ .remove("csp-directive_hidden");
+ this.classList.remove("directive-is-hidden");
+ };
+ heading.addEventListener("click", event => {
+ if (event.target.toggleSection)
+ event.target.toggleSection();
+ });
+ }
+
+ originState.cspDetails.policies.forEach(createPolicySection);
+ }
}
WebInspector.SecurityOriginView.prototype = {

Powered by Google App Engine
This is Rietveld 408576698