[COEP] Improve error messages for COEP

This refactors the implementation and increases color contrast
for the messages.

Bug: chromium:1051473
Change-Id: I21ce4b306d84c6a74fc4182738ab56e6ca952bca
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2089900
Reviewed-by: Peter Marshall <[email protected]>
Commit-Queue: Sigurd Schneider <[email protected]>
diff --git a/front_end/network/RequestHeadersView.js b/front_end/network/RequestHeadersView.js
index 4ad2503..2016dc4 100644
--- a/front_end/network/RequestHeadersView.js
+++ b/front_end/network/RequestHeadersView.js
@@ -124,7 +124,7 @@
   }
 
   /**
-   * @param {!{name:string,value:(string|undefined),headerNotSet:(boolean|undefined),headerValueIncorrect:(boolean|undefined),details:(string|undefined)}} header
+   * @param {!{name:string,value:(string|undefined),headerNotSet:(boolean|undefined),headerValueIncorrect:(boolean|undefined),details:(!{explanation:string,examples:!Array<!{codeSnippet:string,comment:(string|undefined)}>}|undefined)}} header
    * @return {!DocumentFragment}
    */
   _formatHeaderObject(header) {
@@ -143,7 +143,17 @@
       }
     }
     if (header.details) {
-      fragment.createChild('div', 'header-details').innerHTML = header.details;
+      const detailsNode = fragment.createChild('div', 'header-details');
+      const callToAction = detailsNode.createChild('div', 'call-to-action');
+      const callToActionBody = callToAction.createChild('div', 'call-to-action-body');
+      callToActionBody.createChild('div', 'explanation').textContent = header.details.explanation;
+      for (const example of header.details.examples) {
+        const exampleNode = callToActionBody.createChild('div', 'example');
+        exampleNode.createChild('code').textContent = example.codeSnippet;
+        if (example.comment) {
+          exampleNode.createChild('span', 'comment').textContent = example.comment;
+        }
+      }
     }
     return fragment;
   }
@@ -892,27 +902,27 @@
     Protocol.Network.BlockedReason.CoepFrameResourceNeedsCoepHeader, {
       name: 'cross-origin-embedder-policy',
       value: null,
-      details: `<div class='call-to-action'><div class='call-to-action-body'>
-                <div class='explanation'>To embedd this frame in your document,
-                the response needs to enable the Cross Origin Embedder Policy by specifying the following response header:
-                <div class='source-code'>Cross-Origin-Embedder-Policy: require-corp</div>
-                </div>
-            </div>`
+      details: {
+          explanation:
+              ls
+          `To embed this frame in your document, the response needs to enable the cross-origin embedder policy by specifying the following response header:`,
+          examples: [{codeSnippet:'Cross-Origin-Embedder-Policy: require-corp'}]
+      }
     }
   ],
   [
     Protocol.Network.BlockedReason.CorpNotSameOriginAfterDefaultedToSameOriginByCoep, {
       name: 'cross-origin-resource-policy',
       value: null,
-      details: `<div class='call-to-action'><div class='call-to-action-body'>
-                <div class='explanation'>To use this resource from a different origin,
-                  the server needs to specify a <code>Cross-Origin-Resource-Policy<code> response header, e.g.:</div>
-                  <div><code>Cross-Origin-Resource-Policy: same-site</code> &mdash;
-                  Choose this option if the resource and the document are served from the same site.</div>
-              <div><code>Cross-Origin-Resource-Policy: cross-origin</code> &mdash;
-                  <span class='explanation warning'>Only do this if an arbitrary website including this resource does not impose a security risk.</span></div>
-                </div>
-            </div>`
+      details: {
+        explanation:
+            ls
+            `To use this resource from a different origin, the server needs to specify a cross-origin resource policy in the response headers:`,
+        examples: [
+          {codeSnippet:'Cross-Origin-Resource-Policy: same-site', comment: ls`Choose this option if the resource and the document are served from the same site.` },
+          {codeSnippet:'Cross-Origin-Resource-Policy: cross-origin', comment: ls`Only choose this option if an arbitrary website including this resource does not impose a security risk.` },
+        ]
+      }
     }
   ],
   [
@@ -920,10 +930,12 @@
       name: 'cross-origin-opener-policy',
       value: null,
       headerValueIncorrect: false,
-      details: `<div class='call-to-action'><div class='call-to-action-body'>
-             <div class='explanation'>This document was blocked from loading in an <code>iframe</code> with a <code>sandbox</code> attribute because it specified a <code>Cross-Origin-Opener-Policy</code>.</div>
-           </div>
-         </div>`
+      details: {
+        explanation:
+        ls
+        `This document was blocked from loading in an iframe with a sandbox attribute because this document specified a cross-origin opener policy.`,
+        examples: []
+      }
     }
   ],
   [
@@ -931,13 +943,14 @@
       name: 'cross-origin-resource-policy',
       value: null,
       headerValueIncorrect: true,
-      details: `<div class='call-to-action'><div class='call-to-action-body'>
-             <div class='explanation'>To use this resource from a different site,
-               the server may relax the <code>Cross-Origin-Resource-Policy</code> response header:</div>
-               <div><code>Cross-Origin-Resource-Policy: cross-origin</code> &mdash;
-                 <span class='explanation warning'>Only do this if an arbitrary website including this resource does not impose a security risk.</span></div>
-             </div>
-          </div>`
+      details: {
+        explanation:
+            ls
+            `To use this resource from a different site, the server may relax the cross-origin resource policy response header:`,
+        examples: [
+          {codeSnippet:'Cross-Origin-Resource-Policy: cross-origin', comment: ls`Only choose this option if an arbitrary website including this resource does not impose a security risk.` },
+        ]
+      }
     }
   ],
   [
@@ -945,15 +958,15 @@
       name: 'cross-origin-resource-policy',
       value: null,
       headerValueIncorrect: true,
-      details: `<div class='call-to-action'><div class='call-to-action-body'>
-             <div class='explanation'>To use this resource from a different origin,
-             the server may relax the <code>Cross-Origin-Resource-Policy</code> response header:</div>
-             <div><code>Cross-Origin-Resource-Policy: same-site</code> &mdash;
-                 Choose this option if the resource and the document are served from the same site.</div>
-             <div><code>Cross-Origin-Resource-Policy: cross-origin</code> &mdash;
-                 <span class='explanation warning'>Only do this if an arbitrary website including this resource does not impose a security risk.</span></div>
-           </div>
-         </div>`
+      details: {
+        explanation:
+            ls
+            `To use this resource from a different origin, the server may relax the cross-origin resource policy response header:`,
+            examples: [
+              {codeSnippet:'Cross-Origin-Resource-Policy: same-site', comment: ls`Choose this option if the resource and the document are served from the same site.` },
+              {codeSnippet:'Cross-Origin-Resource-Policy: cross-origin', comment: ls`Only choose this option if an arbitrary website including this resource does not impose a security risk.` },
+            ]
+      }
     }
   ],
 ]);
diff --git a/front_end/network/network_strings.grdp b/front_end/network/network_strings.grdp
index 9426c00..bd6d02b 100644
--- a/front_end/network/network_strings.grdp
+++ b/front_end/network/network_strings.grdp
@@ -3,6 +3,9 @@
   <message name="IDS_DEVTOOLS_008aa5b6435af8504757085a92b2eb28" desc="An option in the user agent dropdown menu in the Network conditions tool">
     <ph name="LOCKED_1">Microsoft Edge (EdgeHTML) — XBox</ph>
   </message>
+  <message name="IDS_DEVTOOLS_01687380017f302a17710b4abc47c71c" desc="Text in Headers View of the Network panel">
+    To use this resource from a different site, the server may relax the cross-origin resource policy response header:
+  </message>
   <message name="IDS_DEVTOOLS_0194336f90a2b1de65553e3bec01becd" desc="Text in Network Log View of the Network panel">
     Copy as fetch
   </message>
@@ -132,6 +135,9 @@
   <message name="IDS_DEVTOOLS_2d13df6f8b5e4c5af9f87e0dc39df69d" desc="Text in Network Data Grid Node of the Network panel">
     Pending
   </message>
+  <message name="IDS_DEVTOOLS_2eb301e5055154d55ca33685591c737e" desc="Text in Headers View of the Network panel">
+    To use this resource from a different origin, the server may relax the cross-origin resource policy response header:
+  </message>
   <message name="IDS_DEVTOOLS_2ef0ae0c4d76a87b28176de205d7d346" desc="Text in Network Panel of the Network panel">
     Recording frames...
   </message>
@@ -246,6 +252,9 @@
   <message name="IDS_DEVTOOLS_47d546fc3634f59db7e350acbb01885c" desc="Text in Network Log View of the Network panel">
     <ph name="SELECTEDTRANSFERSIZE">$1s<ex>10</ex></ph> B / <ph name="TRANSFERSIZE">$2s<ex>15</ex></ph> B transferred over network
   </message>
+  <message name="IDS_DEVTOOLS_4909c5e867e2322253bef625307a85a8" desc="Text in Headers View of the Network panel">
+    Only choose this option if an arbitrary website including this resource does not impose a security risk.
+  </message>
   <message name="IDS_DEVTOOLS_490aa6e856ccf208a054389e47ce0d06" desc="Text in Event Source Messages View of the Network panel">
     Id
   </message>
@@ -276,6 +285,9 @@
   <message name="IDS_DEVTOOLS_5101cdda28ea3097ac00cdbfdcedc353" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
     Use default colors
   </message>
+  <message name="IDS_DEVTOOLS_5223b56f806ed0547f295a2c643061ec" desc="Text in Headers View of the Network panel">
+    To use this resource from a different origin, the server needs to specify a cross-origin resource policy in the response headers:
+  </message>
   <message name="IDS_DEVTOOLS_52c2263c92c8b0f41e36892ccd8cb119" desc="Accessible label for the button to add request blocking patterns in the Request blocking tool">
     Add request blocking pattern
   </message>
@@ -390,6 +402,9 @@
   <message name="IDS_DEVTOOLS_82764787c77b4c9e53993b15d31a11c5" desc="Text to announce to screen readers that network data is available.">
     Network Data Available
   </message>
+  <message name="IDS_DEVTOOLS_8470bd9052ed82990d6e49335b14e41e" desc="Text in Headers View of the Network panel">
+    This document was blocked from loading in an <ph name="LOCKED_1">iframe</ph> with a <ph name="LOCKED_1">sandbox</ph> attribute because this document specified a cross-origin opener policy.
+  </message>
   <message name="IDS_DEVTOOLS_b23be8e9d2dc9b79c70ec2acd3f174d3" desc="Label for the Server Timing API">
     the Server Timing API
   </message>
@@ -408,6 +423,9 @@
   <message name="IDS_DEVTOOLS_c21b43091d5f2cb131e79122289ce033" desc="Text in Network Log View of the Network panel">
     <ph name="SELECTEDRESOURCESIZE">$1s<ex>40</ex></ph> B / <ph name="RESOURCESIZE">$2s<ex>50</ex></ph> B resources loaded by the page
   </message>
+  <message name="IDS_DEVTOOLS_c823a983a972cfb5ee4b8bf1918080d3" desc="Text in Headers View of the Network panel">
+    Choose this option if the resource and the document are served from the same site.
+  </message>
   <message name="IDS_DEVTOOLS_ca092ce554360617d7bb503ff16dcb7c" desc="Text for toggling the view of header data (e.g. query string parameters) from parsed to source in the headers tab">
     View source
   </message>
@@ -438,6 +456,9 @@
   <message name="IDS_DEVTOOLS_decbe8975cc2421194a7c86283fef5e4" desc="Text in Network Data Grid Node of the Network panel">
     NotSameOrigin
   </message>
+  <message name="IDS_DEVTOOLS_e2cfb91cd8426f99401143d41343faff" desc="Text in Headers View of the Network panel">
+    To embed this frame in your document, the response needs to enable the cross-origin embedder policy by specifying the following response header:
+  </message>
   <message name="IDS_DEVTOOLS_e4217cfa8bdee0baaa2249db59b8671b" desc="Text for toggling the view of header data (e.g. query string parameters) from source to parsed in the headers tab">
     View parsed
   </message>
diff --git a/front_end/network/requestHeadersTree.css b/front_end/network/requestHeadersTree.css
index ca0072f..05b984e 100644
--- a/front_end/network/requestHeadersTree.css
+++ b/front_end/network/requestHeadersTree.css
@@ -134,8 +134,13 @@
     font-weight: bold;
 }
 
-.tree-outline .call-to-action .explanation.warning {
-    color: var(--error-background-color);
+.tree-outline .call-to-action code {
+    font-size: 90%;
+}
+
+
+.tree-outline .call-to-action .example .comment::before {
+   content: " — ";
 }
 
 .tree-outline .empty-request-header {