Migrate chrome://traces-internals to Lit, part 3

This part focus on removing all the remaining polymer dependencies from
chrome://traces-internals. Also, removes /resources/traces_internals
from the polymer build.

Also, this changes the format of the existent html.ts files.

Bug:350938143

Change-Id: Ib9ca117e3044715002ca3e7738311142c7147860
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5677041
Reviewed-by: Demetrios Papadopoulos <dpapad@chromium.org>
Reviewed-by: Etienne Pierre-Doray <etiennep@chromium.org>
Commit-Queue: Alex Attar <aattar@google.com>
Cr-Commit-Position: refs/heads/main@{#1333717}
diff --git a/content/browser/resources/traces_internals/BUILD.gn b/content/browser/resources/traces_internals/BUILD.gn
index 5962e07..86fe574 100644
--- a/content/browser/resources/traces_internals/BUILD.gn
+++ b/content/browser/resources/traces_internals/BUILD.gn
@@ -30,13 +30,11 @@
 
   ts_deps = [
     "//third_party/lit/v3_0:build_ts",
-    "//third_party/polymer/v3_0:library",
     "//ui/webui/resources/cr_elements:build_ts",
     "//ui/webui/resources/js:build_ts",
     "//ui/webui/resources/mojo:build_ts",
   ]
 
-  ts_composite = true
   webui_context_type = "trusted"
 
   mojo_files_deps =
diff --git a/content/browser/resources/traces_internals/icons.html b/content/browser/resources/traces_internals/icons.html
index 8a47a8b..a71ca5ff 100644
--- a/content/browser/resources/traces_internals/icons.html
+++ b/content/browser/resources/traces_internals/icons.html
@@ -1,4 +1,4 @@
-<iron-iconset-svg name="trace-report-icons" size="24">
+<cr-iconset name="trace-report-icons" size="24">
   <svg>
     <defs>
     <!-- See http://goo.gl/Y1OdAq for instructions on adding additional icons. -->
@@ -8,4 +8,4 @@
     <g id="cloud_upload" viewBox="0 -960 960 960"><path d="M260-160q-91 0-155.5-63T40-377q0-78 47-139t123-78q25-92 100-149t170-57q117 0 198.5 81.5T760-520q69 8 114.5 59.5T920-340q0 75-52.5 127.5T740-160H520q-33 0-56.5-23.5T440-240v-206l-64 62-56-56 160-160 160 160-56 56-64-62v206h220q42 0 71-29t29-71q0-42-29-71t-71-29h-60v-80q0-83-58.5-141.5T480-720q-83 0-141.5 58.5T280-520h-20q-58 0-99 41t-41 99q0 58 41 99t99 41h100v80H260Zm220-280Z"></path></g>
     </defs>
   </svg>
-</iron-iconset-svg>
\ No newline at end of file
+</cr-iconset>
\ No newline at end of file
diff --git a/content/browser/resources/traces_internals/trace_report.css b/content/browser/resources/traces_internals/trace_report.css
index 9b99599..11a3e39 100644
--- a/content/browser/resources/traces_internals/trace_report.css
+++ b/content/browser/resources/traces_internals/trace_report.css
@@ -9,7 +9,7 @@
  * #include=cr-hidden-style-lit
  * #css_wrapper_metadata_end */
 
-.trace-card {
+:host {
   display: grid;
   grid-template-columns: 1fr 1fr 1fr 3fr auto auto auto;
   grid-auto-flow: column;
@@ -26,7 +26,7 @@
   position: relative;
 }
 
-.trace-card > div {
+:host > div {
   overflow: hidden;
   min-width: 0;
 }
@@ -171,7 +171,19 @@
   border-radius: 4px;
 }
 
-.trace-spinner > paper-spinner-lite {
-  width: 20px;
-  height: 20px;
+.spinner {
+  --spinner-size: 20px;
+  mask-image: url(chrome://resources/images/throbber_small.svg);
+  mask-position: center;
+  mask-repeat: no-repeat;
+  background-color: var(--google-blue-500);
+  mask-size: var(--spinner-size) var(--spinner-size);
+  height: var(--spinner-size);
+  width: var(--spinner-size);
+}
+
+@media (prefers-color-scheme: dark) {
+  .spinner {
+    background-color: var(--google-blue-300);
+  }
 }
diff --git a/content/browser/resources/traces_internals/trace_report.html.ts b/content/browser/resources/traces_internals/trace_report.html.ts
index 9fe6aa11..919562f 100644
--- a/content/browser/resources/traces_internals/trace_report.html.ts
+++ b/content/browser/resources/traces_internals/trace_report.html.ts
@@ -2,94 +2,70 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {html} from 'chrome://resources/lit/v3_0/lit.rollup.js';
+import {html} from '//resources/lit/v3_0/lit.rollup.js';
 
 import type {TraceReportElement} from './trace_report.js';
+import {ReportUploadState} from './trace_report.mojom-webui.js';
 
 export function getHtml(this: TraceReportElement) {
   // clang-format off
   return html`
-    <div class="trace-card">
-      ${this.isLoading ? html`
-        <div class="trace-spinner">
-          <paper-spinner-lite active></paper-spinner-lite>
-        </div>` : ''}
-      <div class="trace-id-container">
-        <button class="clickable-field copiable"
-            @click="${this.onCopyUuidClick_}"
-            title="${this.tokenToString_(this.trace.uuid)}">
-          ${this.tokenToString_(this.trace.uuid)}
-        </button>
-        <div class="info">Trace ID</div>
+    ${this.isLoading_ ? html`<div class="spinner"></div>` :
+    html`
+    <div class="trace-id-container">
+      <button class="clickable-field copiable" title="${this.getTokenAsString_()}"
+          @click="${this.onCopyUuidClick_}">
+        ${this.getTokenAsString_()}
+      </button>
+      <div class="info">Trace ID</div>
+    </div>
+    <div class="trace-date-created-container">
+      <div class="date-creation-value">
+        ${this.dateToString_(this.trace.creationTime)}
       </div>
-      <div class="trace-date-created-container">
-        <div class="date-creation-value">
-          ${this.dateToString_(this.trace.creationTime)}
-        </div>
-        <div class="info">Date created</div>
+      <div class="info">Date created</div>
+    </div>
+    <div class="trace-scenario-container">
+      <button class="clickable-field copiable" title="${this.trace.scenarioName}"
+          @click="${this.onCopyScenarioClick_}">
+        ${this.trace.scenarioName}
+      </button>
+    </div>
+    <div class="trace-trigger-container">
+      <button class="clickable-field copiable" title="${this.trace.uploadRuleName}"
+          @click="${this.onCopyUploadRuleClick_}">
+        ${this.trace.uploadRuleName}
+      </button>
+      <div class="info">Trigger rule</div>
+    </div>
+    <div class="trace-size-container">
+      <div class="trace-size-value">${this.getTraceSize_()}</div>
+      <div class="info">Uncompressed size</div>
+    </div>
+    <div class="trace-upload-state-container">
+      <div class="upload-state-card ${this.getStateCssClass_()}"
+        title="${this.getStateText_()}">
+        ${this.getStateText_()}
       </div>
-      <div class="trace-scenario-container">
-        <button class="clickable-field copiable"
-            @click="${this.onCopyScenarioClick_}"
-            title="${this.trace.scenarioName}">
-          ${this.trace.scenarioName}
-        </button>
-      </div>
-      <div class="trace-trigger-container">
-        <button class="clickable-field copiable"
-            @click="${this.onCopyUploadRuleClick_}"
-            title="${this.trace.uploadRuleName}">
-          ${this.trace.uploadRuleName}
-        </button>
-        <div class="info">Trigger rule</div>
-      </div>
-      <div class="trace-size-container">
-        <div class="trace-size-value">${this.getTraceSize_()}</div>
-        <div class="info">Uncompressed size</div>
-      </div>
-      <div class="trace-upload-state-container">
-        <div class="upload-state-card state-default"
-            ?hidden="${!this.uploadStateEqual_(
-                this.uploadStateEnum_.NOT_UPLOADED)}"
-            title="Skip reason: ${this.getSkipReason_()}">
-          Skip reason: ${this.getSkipReason_()}
-        </div>
-        <div class="upload-state-card state-pending"
-            ?hidden="${!this.uploadStateEqual_(this.uploadStateEnum_.PENDING)}">
-          Pending upload
-        </div>
-        <div class="upload-state-card state-pending"
-            ?hidden="${!this.uploadStateEqual_(
-                this.uploadStateEnum_.USER_REQUEST)}">
-          Pending upload: User requested
-        </div>
-        <div class="upload-state-card state-success"
-            ?hidden="${!this.uploadStateEqual_(
-                this.uploadStateEnum_.UPLOADED)}">
-          Uploaded: ${this.dateToString_(this.trace.uploadTime)}
-        </div>
-      </div>
-      <div class="actions-container">
-        <cr-icon-button class="action-button" title="Upload Trace"
-            iron-icon="trace-report-icons:cloud_upload"
-            aria-label="Upload Trace" @click="${this.onUploadTraceClick_}"
-            ?hidden="${!this.uploadStateEqual_(
-                this.uploadStateEnum_.NOT_UPLOADED)}"
-            ?disabled="${!this.isManualUploadPermitted_(
-                this.trace.skipReason)}">
-        </cr-icon-button>
-        <cr-icon-button class="action-button" iron-icon="cr:file-download"
-            title="${this.getDownloadTooltip_()}"
-            @click="${this.onDownloadTraceClick_}"
-            ?disabled="${this.isDownloadDisabled_()}"
-            aria-label="${this.getDownloadTooltip_()}">
-        </cr-icon-button>
-        <cr-icon-button class="action-button" iron-icon="cr:delete"
-            title="Delete Trace" @click="${this.onDeleteTraceClick_}"
-            ?disabled="${this.isLoading}"
-            aria-label="Delete Trace">
-        </cr-icon-button>
-      </div>
-    </div>`;
+    </div>
+    <div class="actions-container">
+      <cr-icon-button class="action-button" title="Upload Trace"
+          iron-icon="trace-report-icons:cloud_upload" aria-label="Upload Trace"
+          ?hidden="${!this.uploadStateEqual_(ReportUploadState.kNotUploaded)}"
+          ?disabled="${!this.isManualUploadPermitted_()}"
+          @click="${this.onUploadTraceClick_}">
+      </cr-icon-button>
+      <cr-icon-button class="action-button" iron-icon="cr:file-download"
+          title="Download Trace" @click="${this.onDownloadTraceClick_}"
+          ?disabled="${this.isDownloadDisabled_()}"
+          aria-label="Download Trace">
+      </cr-icon-button>
+      <cr-icon-button class="action-button" iron-icon="cr:delete"
+          title="Delete Trace" @click="${this.onDeleteTraceClick_}"
+          ?disabled="${this.isLoading_}"
+          aria-label="Delete Trace">
+      </cr-icon-button>
+    </div>
+  `}`;
   // clang-format on
 }
diff --git a/content/browser/resources/traces_internals/trace_report.ts b/content/browser/resources/traces_internals/trace_report.ts
index 5cfeb9d5..717e605c3 100644
--- a/content/browser/resources/traces_internals/trace_report.ts
+++ b/content/browser/resources/traces_internals/trace_report.ts
@@ -3,30 +3,20 @@
 // found in the LICENSE file.
 
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
-import 'chrome://resources/cr_elements/icons.html.js';
-import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
+import 'chrome://resources/cr_elements/icons_lit.html.js';
 import './icons.html.js';
 
 import {assert} from 'chrome://resources/js/assert.js';
 import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 import type {BigBuffer} from 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-webui.js';
 import type {Time} from 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-webui.js';
-import type {Token} from 'chrome://resources/mojo/mojo/public/mojom/base/token.mojom-webui.js';
 
 import {getCss} from './trace_report.css.js';
 import {getHtml} from './trace_report.html.js';
 import type {ClientTraceReport} from './trace_report.mojom-webui.js';
-import {SkipUploadReason} from './trace_report.mojom-webui.js';
+import {ReportUploadState, SkipUploadReason} from './trace_report.mojom-webui.js';
 import {TraceReportBrowserProxy} from './trace_report_browser_proxy.js';
-import {Notification, NotificationTypeEnum} from './trace_report_list.js';
-
-enum UploadState {
-  NOT_UPLOADED = 0,
-  PENDING = 1,
-  USER_REQUEST = 2,
-  UPLOADED = 3,
-}
+import {Notification, NotificationType} from './trace_report_list.js';
 
 // Create the temporary element here to hold the data to download the trace
 // since it is only obtained after downloadData_ is called. This way we can
@@ -56,53 +46,33 @@
   static override get properties() {
     return {
       trace: {type: Object},
-      // Enable the html template to use UploadState
-      uploadStateEnum_: {type: Object},
       isLoading: {type: Boolean},
     };
   }
 
-  protected trace: ClientTraceReport;
-  protected isLoading: boolean = false;
-  protected uploadStateEnum_: typeof UploadState = UploadState;
   private traceReportProxy_: TraceReportBrowserProxy =
       TraceReportBrowserProxy.getInstance();
 
+  protected trace: ClientTraceReport = {
+    // Dummy ClientTraceReport
+    uuid: {
+      high: 0n,
+      low: 0n,
+    },
+    creationTime: {internalValue: 0n},
+    scenarioName: '',
+    uploadRuleName: '',
+    totalSize: 0n,
+    uploadState: ReportUploadState.kNotUploaded,
+    uploadTime: {internalValue: 0n},
+    skipReason: SkipUploadReason.kNoSkip,
+    hasTraceContent: false,
+  };
+  protected isLoading_: boolean = false;
+
   protected onCopyUuidClick_(): void {
     // Get the text field
-    assert(this.trace.uuid.high);
-    assert(this.trace.uuid.low);
-    navigator.clipboard.writeText(this.tokenToString_(this.trace.uuid));
-  }
-
-  protected onCopyScenarioClick_(): void {
-    // Get the text field
-    assert(this.trace.scenarioName);
-    navigator.clipboard.writeText(this.trace.scenarioName);
-  }
-
-  protected onCopyUploadRuleClick_(): void {
-    // Get the text field
-    assert(this.trace.uploadRuleName);
-    navigator.clipboard.writeText(this.trace.uploadRuleName);
-  }
-
-  protected getSkipReason_(): string {
-    // Keep this in sync with the values of SkipUploadReason in
-    // trace_report.mojom
-    const skipReasonMap: string[] = [
-      'None',
-      'Size limit exceeded',
-      'Not anonymized',
-      'Scenario quota exceeded',
-      'Upload timed out',
-    ];
-
-    return skipReasonMap[this.trace.skipReason];
-  }
-
-  protected isManualUploadPermitted_(skipReason: number): boolean {
-    return skipReason !== SkipUploadReason.kNotAnonymized;
+    navigator.clipboard.writeText(this.getTokenAsString_());
   }
 
   protected getTraceSize_(): string {
@@ -124,6 +94,35 @@
     return `${displayedSize.toFixed(2)} ${sizes[i]}`;
   }
 
+  protected getSkipReason_(): string {
+    // Keep this in sync with the values of SkipUploadReason in
+    // tracereport.mojom
+    const skipReasonMap: string[] = [
+      'None',
+      'Size limit exceeded',
+      'Not anonymized',
+      'Scenario quota exceeded',
+      'Upload timed out',
+    ];
+
+    return skipReasonMap[this.trace.skipReason] ??
+        'Could not get the skip reason';
+  }
+
+  protected onCopyScenarioClick_(): void {
+    // Get the text field
+    navigator.clipboard.writeText(this.trace.scenarioName);
+  }
+
+  protected onCopyUploadRuleClick_(): void {
+    // Get the text field
+    navigator.clipboard.writeText(this.trace.uploadRuleName);
+  }
+
+  protected isManualUploadPermitted_(): boolean {
+    return this.trace.skipReason !== SkipUploadReason.kNotAnonymized;
+  }
+
   protected dateToString_(mojoTime: Time): string {
     // The JS Date() is based off of the number of milliseconds since
     // the UNIX epoch (1970-01-01 00::00:00 UTC), while |internalValue|
@@ -153,22 +152,21 @@
   }
 
   protected async onDownloadTraceClick_(): Promise<void> {
-    this.isLoading = true;
+    this.isLoading_ = true;
     const {trace} =
         await this.traceReportProxy_.handler.downloadTrace(this.trace.uuid);
     if (trace !== null) {
-      this.downloadData_(`${this.tokenToString_(this.trace.uuid)}.gz`, trace);
+      this.downloadData_(`${this.getTokenAsString_()}.gz`, trace);
     } else {
-      this.dispatchToast_(
-          `Failed to download trace ${this.tokenToString_(this.trace.uuid)}.`);
+      this.dispatchToast_(`Failed to download trace ${this.getTokenAsString_()}.`);
     }
-    this.isLoading = false;
+    this.isLoading_ = false;
   }
 
   private downloadData_(fileName: string, data: BigBuffer): void {
     if (data.invalidBuffer) {
-      this.dispatchToast_(`Invalid buffer received for ${
-          this.tokenToString_(this.trace.uuid)}.`);
+      this.dispatchToast_(
+          `Invalid buffer received for ${this.getTokenAsString_()}.`);
       return;
     }
     try {
@@ -187,65 +185,93 @@
           new Blob([bytes], {type: 'application/octet-stream'}));
       downloadUrl(fileName, url);
     } catch (e) {
-      this.dispatchToast_(`Unable to create blob from trace data for ${
-          this.tokenToString_(this.trace.uuid)}.`);
+      this.dispatchToast_(
+          `Unable to create blob from trace data for ${this.getTokenAsString_()}.`);
     }
   }
 
   protected async onDeleteTraceClick_(): Promise<void> {
-    this.isLoading = true;
+    this.isLoading_ = true;
     const {success} =
         await this.traceReportProxy_.handler.deleteSingleTrace(this.trace.uuid);
     if (!success) {
-      this.dispatchToast_(
-          `Failed to delete ${this.tokenToString_(this.trace.uuid)}.`);
+      this.dispatchToast_(`Failed to delete ${this.getTokenAsString_()}.`);
     } else {
       this.dispatchReloadRequest_();
     }
-    this.isLoading = false;
+    this.isLoading_ = false;
   }
 
   protected async onUploadTraceClick_(): Promise<void> {
-    this.isLoading = true;
+    this.isLoading_ = true;
     const {success} =
         await this.traceReportProxy_.handler.userUploadSingleTrace(
             this.trace.uuid);
     if (!success) {
-      this.dispatchToast_(
-          `Failed to upload trace ${this.tokenToString_(this.trace.uuid)}.`);
+      this.dispatchToast_(`Failed to upload trace ${this.getTokenAsString_()}.`);
     } else {
       this.dispatchReloadRequest_();
     }
-    this.isLoading = false;
+    this.isLoading_ = false;
   }
 
-  protected uploadStateEqual_(state: UploadState): boolean {
-    return this.trace.uploadState === state as number;
+  protected uploadStateEqual_(state: ReportUploadState): boolean {
+    return this.trace.uploadState === state;
   }
 
-  protected tokenToString_(token: Token): string {
-    return `${token.high.toString(16)}-${token.low.toString(16)}`;
+  protected getTokenAsString_(): string {
+    return `${this.trace.uuid.high.toString(16)}-${
+        this.trace.uuid.low.toString(16)}`;
   }
 
   private dispatchToast_(message: string): void {
     this.dispatchEvent(new CustomEvent('show-toast', {
       bubbles: true,
       composed: true,
-      detail: new Notification(NotificationTypeEnum.ERROR, message),
+      detail: new Notification(NotificationType.ERROR, message),
     }));
   }
 
   protected isDownloadDisabled_(): boolean {
-    return this.isLoading || !this.trace.hasTraceContent;
+    return this.isLoading_ || !this.trace.hasTraceContent;
   }
 
   protected getDownloadTooltip_(): string {
-    return this.trace.hasTraceContent ? 'Dowload Trace' : 'Trace expired';
+    return this.trace.hasTraceContent ? 'Download Trace' : 'Trace expired';
   }
 
   private dispatchReloadRequest_(): void {
     this.fire('refresh-traces-request');
   }
+
+  protected getStateCssClass_(): string {
+    switch (this.trace.uploadState) {
+      case ReportUploadState.kNotUploaded:
+        return 'state-default';
+      case ReportUploadState.kPending:
+      case ReportUploadState.kPending_UserRequested:
+        return 'state-pending';
+      case ReportUploadState.kUploaded:
+        return 'state-success';
+      default:
+        return '';
+    }
+  }
+
+  protected getStateText_(): string {
+    switch (this.trace.uploadState) {
+      case ReportUploadState.kNotUploaded:
+        return `Skip reason: ${this.getSkipReason_()}`;
+      case ReportUploadState.kPending:
+        return 'Pending upload';
+      case ReportUploadState.kPending_UserRequested:
+        return 'Pending upload: User requested';
+      case ReportUploadState.kUploaded:
+        return `Uploaded: ${this.dateToString_(this.trace.uploadTime)}`;
+      default:
+        return '';
+    }
+  }
 }
 
 declare global {
diff --git a/content/browser/resources/traces_internals/trace_report_list.css b/content/browser/resources/traces_internals/trace_report_list.css
index 3cc3164..3c71dd0 100644
--- a/content/browser/resources/traces_internals/trace_report_list.css
+++ b/content/browser/resources/traces_internals/trace_report_list.css
@@ -14,7 +14,7 @@
 }
 
 h1 > .trace-counter {
-  margin-left: 14px;
+  margin-inline-start: 14px;
 }
 
 .loading-spinner {
@@ -24,9 +24,21 @@
   justify-content: center;
 }
 
-.loading-spinner > paper-spinner-lite {
-  width: 60px;
-  height: 60px;
+.spinner {
+  --spinner-size: 60px;
+  mask-image: url(chrome://resources/images/throbber_medium.svg);
+  mask-position: center;
+  mask-repeat: no-repeat;
+  background-color: var(--google-blue-500);
+  mask-size: var(--spinner-size) var(--spinner-size);
+  height: var(--spinner-size);
+  width: var(--spinner-size);
+}
+
+@media (prefers-color-scheme: dark) {
+  .spinner {
+    background-color: var(--google-blue-300);
+  }
 }
 
 #notification-card {
@@ -66,25 +78,25 @@
   display: flex;
   justify-content: center;
   align-items: center;
-  margin-right: 24px;
+  margin-inline-end: 24px;
   height: auto;
 }
 
-.icon-container > iron-icon {
+.icon-container > cr-icon {
   --iron-icon-fill-color: white;
   --iron-icon-width: 40px;
   --iron-icon-height: 40px;
 }
 
-.icon-container.error > iron-icon {
+.icon-container.error > cr-icon {
   --iron-icon-fill-color: rgb(195, 40, 40);
 }
 
-.icon-container.accouncement > iron-icon {
+.icon-container.accouncement > cr-icon {
   --iron-icon-fill-color: rgb(98, 133, 52);
 }
 
-.icon-container.update > iron-icon {
+.icon-container.update > cr-icon {
   --iron-icon-fill-color: rgb(34, 135, 211);
 }
 
diff --git a/content/browser/resources/traces_internals/trace_report_list.html.ts b/content/browser/resources/traces_internals/trace_report_list.html.ts
index 98936190..9b33143 100644
--- a/content/browser/resources/traces_internals/trace_report_list.html.ts
+++ b/content/browser/resources/traces_internals/trace_report_list.html.ts
@@ -2,58 +2,62 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {html} from 'chrome://resources/lit/v3_0/lit.rollup.js';
+import {html, nothing} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 
+import type {ClientTraceReport} from './trace_report.mojom-webui.js';
 import type {TraceReportListElement} from './trace_report_list.js';
 
+function getReportHtml(this: TraceReportListElement) {
+  // clang-format off
+  if (!this.hasTraces_()) {
+    return html`
+    <div class="empty-message">
+      <cr-icon icon="cr:warning"></cr-icon>
+      <h1>Could not find any traces saved locally.</h1>
+    </div>`;
+  }
+
+  return html`${this.traces_.map((traceReport: ClientTraceReport) => html`
+    <trace-report .trace="${traceReport}"></trace-report>`)}`;
+  // clang-format on
+}
+
 export function getHtml(this: TraceReportListElement) {
   // clang-format off
   return html`
-    <div class="traces-header">
-      <h1>Traces
-        <span class="trace-counter" ?hidden="${!this.hasTraces_()}">
-          ${this.traces.length}
-        </span>
-      </h1>
+  <div class="traces-header">
+    <h1>Traces
+      <span class="trace-counter" ?hidden="${!this.hasTraces_()}">
+        ${this.traces_.length}
+      </span>
+    </h1>
+    ${this.hasTraces_() ? html`<div class="utility-bar">
+    <cr-button class="floating-button" ?disabled="${!this.hasTraces_()}"
+        @click="${this.onDeleteAllTracesClick_}">
+      <cr-icon icon="cr:delete" aria-hidden="true"></cr-icon>
+      Delete All Traces
+    </cr-button>` : nothing}
+  </div>
+  ${this.isLoading_ ? html`
+  <div class="loading-spinner"><div class="spinner"></div></div>` :
+  html`
+  <div class="report-list-container">
+    ${getReportHtml.bind(this)()}
+  </div>`}
+  <cr-toast id="toast" duration="5000" ?hidden="${!this.notification_}">
+    <div id="notification-card">
+      <div class="icon-container ${this.getNotificationStyling_()}">
+        <cr-icon icon="${this.getNotificationIcon_()}"
+            aria-hidden="true">
+        </cr-icon>
+      </div>
+      <div class="notification-message">
+        <h4 class="notification-type ${this.getNotificationStyling_()}">
+          ${this.getNotificationType_()}
+        </h4>
+        <span class="notification-label">${this.getNotificationLabel_()}</span>
+      </div>
     </div>
-    ${this.isLoading ? html`
-      <div class="loading-spinner">
-        <paper-spinner-lite ?active="${this.isLoading}">
-        </paper-spinner-lite>
-      </div>` : ''}
-
-    ${!this.isLoading && this.hasTraces_() ? html`
-      <div class="utility-bar">
-        <cr-button class="floating-button"
-            ?disabled="${!this.hasTraces_()}"
-            @click="${this.onDeleteAllTracesClick_}">
-          <iron-icon icon="cr:delete" aria-hidden="true"></iron-icon>
-          Delete All Traces
-        </cr-button>
-      </div>
-      ${this.traces.map(item => html`
-        <trace-report .trace="${item}" @show-toast="${this.showToastHandler_}"
-            @refresh-traces-request="${this.initializeList}">
-        </trace-report>
-        `)}` : html`
-      <div class="empty-message" ?hidden="${this.hasTraces_()}">
-        <iron-icon icon="cr:warning"></iron-icon>
-        <h1>Could not find any traces saved locally.</h1>
-      </div>`}
-
-    <cr-toast id="toast" duration="5000" ?hidden="${!this.notification}">
-      <div id="notification-card">
-        <div class="icon-container ${this.getNotificationStyling_()}">
-          <iron-icon icon="${this.getNotificationIcon_()}" aria-hidden="true">
-          </iron-icon>
-        </div>
-        <div class="notification-message">
-          <h4 class="notification-type ${this.getNotificationStyling_()}">
-            ${this.notification.type}
-          </h4>
-          <span class="notification-label">${this.notification.label}</span>
-        </div>
-      </div>
-    </cr-toast>`;
+  </cr-toast>`;
   // clang-format on
 }
diff --git a/content/browser/resources/traces_internals/trace_report_list.ts b/content/browser/resources/traces_internals/trace_report_list.ts
index 5fa5c4a8..14bb395e8b 100644
--- a/content/browser/resources/traces_internals/trace_report_list.ts
+++ b/content/browser/resources/traces_internals/trace_report_list.ts
@@ -5,8 +5,8 @@
 import './trace_report.js';
 import 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
-import 'chrome://resources/cr_elements/icons.html.js';
-import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
+import 'chrome://resources/cr_elements/cr_icon/cr_icon.js';
+import 'chrome://resources/cr_elements/icons_lit.html.js';
 
 import type {CrToastElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
 import {assert} from 'chrome://resources/js/assert.js';
@@ -18,19 +18,17 @@
 import {getHtml} from './trace_report_list.html.js';
 // clang-format on
 
-export enum NotificationTypeEnum {
+export enum NotificationType {
   UPDATE = 'Update',
   ERROR = 'Error',
   ANNOUNCEMENT = 'Announcement'
 }
 
 export class Notification {
-  readonly type: NotificationTypeEnum;
+  readonly type: NotificationType;
   readonly label: string;
-  readonly icon: string;
-  readonly style: string;
 
-  constructor(type: NotificationTypeEnum, label: string) {
+  constructor(type: NotificationType, label: string) {
     this.type = type;
     this.label = label;
   }
@@ -57,23 +55,17 @@
 
   static override get properties() {
     return {
-      traces: {
-        type: Array,
-      },
-      isLoading: {
-        type: Boolean,
-      },
-      notification: {
-        type: Notification,
-      },
+      traces_: {type: Array},
+      isLoading_: {type: Boolean},
+      notification: {type: Notification},
     };
   }
 
   private traceReportProxy_: TraceReportBrowserProxy =
       TraceReportBrowserProxy.getInstance();
-  protected traces: ClientTraceReport[] = [];
-  protected isLoading: boolean = false;
-  protected notification: Readonly<Notification>;
+  protected traces_: ClientTraceReport[] = [];
+  protected isLoading_: boolean = false;
+  protected notification_?: Readonly<Notification>;
 
   override connectedCallback(): void {
     super.connectedCallback();
@@ -81,60 +73,62 @@
   }
 
   protected async initializeList(hasLoading: boolean = false): Promise<void> {
-    this.isLoading = hasLoading;
+    this.isLoading_ = hasLoading;
     const {reports} = await this.traceReportProxy_.handler.getAllTraceReports();
     if (reports) {
-      this.traces = reports;
+      this.traces_ = reports;
     } else {
-      this.traces = [];
-      this.notification = new Notification(
-          NotificationTypeEnum.ERROR,
+      this.traces_ = [];
+      this.notification_ = new Notification(
+          NotificationType.ERROR,
           'Error: Could not retrieve any trace reports.');
       this.$.toast.show();
     }
-    this.isLoading = false;
+    this.isLoading_ = false;
+  }
+
+  protected hasTraces_(): boolean {
+    return this.traces_.length > 0;
   }
 
   protected showToastHandler_(e: CustomEvent<Notification>): void {
     assert(e.detail);
-    this.notification = e.detail;
+    this.notification_ = e.detail;
     this.$.toast.show();
   }
 
   protected getNotificationIcon_(): string {
-    if (this.notification === undefined) {
-      return '';
-    }
-    switch (this.notification.type) {
-      case NotificationTypeEnum.ANNOUNCEMENT:
+    switch (this.getNotificationType_()) {
+      case NotificationType.ANNOUNCEMENT:
         return 'cr:info-outline';
-      case NotificationTypeEnum.ERROR:
+      case NotificationType.ERROR:
         return 'cr:error-outline';
-      case NotificationTypeEnum.UPDATE:
+      case NotificationType.UPDATE:
         return 'cr:sync';
       default:
-        return '';
+        return 'cr:warning';
     }
   }
 
   protected getNotificationStyling_(): string {
-    if (this.notification === undefined) {
-      return '';
-    }
-    switch (this.notification.type) {
-      case NotificationTypeEnum.ANNOUNCEMENT:
+    switch (this.getNotificationType_()) {
+      case NotificationType.ANNOUNCEMENT:
         return 'announcement';
-      case NotificationTypeEnum.ERROR:
+      case NotificationType.ERROR:
         return 'error';
-      case NotificationTypeEnum.UPDATE:
+      case NotificationType.UPDATE:
         return 'update';
       default:
         return '';
     }
   }
 
-  protected hasTraces_(): boolean {
-    return this.traces.length > 0;
+  protected getNotificationLabel_(): string {
+    return this.notification_?.label || '';
+  }
+
+  protected getNotificationType_(): string {
+    return this.notification_?.type || '';
   }
 
   protected async onDeleteAllTracesClick_(): Promise<void> {
@@ -149,7 +143,7 @@
     this.dispatchEvent(new CustomEvent('show-toast', {
       bubbles: true,
       composed: true,
-      detail: new Notification(NotificationTypeEnum.ERROR, message),
+      detail: new Notification(NotificationType.ERROR, message),
     }));
   }
 }
diff --git a/third_party/polymer/v3_0/BUILD.gn b/third_party/polymer/v3_0/BUILD.gn
index 48a4392..3647477 100644
--- a/third_party/polymer/v3_0/BUILD.gn
+++ b/third_party/polymer/v3_0/BUILD.gn
@@ -159,7 +159,6 @@
     "//chrome/test/data/webui/side_panel/read_anything:build_ts",
     "//chrome/test/data/webui/signin:build_ts",
     "//chrome/test/data/webui/support_tool:build_ts",
-    "//content/browser/resources/traces_internals:build_ts",
     "//ui/webui/resources/cr_components/certificate_manager:build_ts",
     "//ui/webui/resources/cr_components/customize_themes:build_ts",
     "//ui/webui/resources/cr_components/help_bubble:build_ts",