UNPKG

chrome-devtools-frontend

Version:
175 lines (152 loc) • 7.4 kB
// Copyright 2024 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import '../../../ui/components/icon_button/icon_button.js'; import * as i18n from '../../../core/i18n/i18n.js'; import * as Platform from '../../../core/platform/platform.js'; import * as Trace from '../../../models/trace/trace.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as Lit from '../../../ui/lit/lit.js'; import networkRequestTooltipStylesRaw from './networkRequestTooltip.css.js'; import {colorForNetworkRequest, networkResourceCategory} from './Utils.js'; // TODO(crbug.com/391381439): Fully migrate off of constructed style sheets. const networkRequestTooltipStyles = new CSSStyleSheet(); networkRequestTooltipStyles.replaceSync(networkRequestTooltipStylesRaw.cssContent); const {html} = Lit; const MAX_URL_LENGTH = 60; const UIStrings = { /** *@description Text that refers to the priority of network request */ priority: 'Priority', /** *@description Text for the duration of a network request */ duration: 'Duration', /** *@description Text that refers to the queueing and connecting time of a network request */ queuingAndConnecting: 'Queuing and connecting', /** *@description Text that refers to the request sent and waiting time of a network request */ requestSentAndWaiting: 'Request sent and waiting', /** *@description Text that refers to the content downloading time of a network request */ contentDownloading: 'Content downloading', /** *@description Text that refers to the waiting on main thread time of a network request */ waitingOnMainThread: 'Waiting on main thread', /** *@description Text that refers to a network request is render blocking */ renderBlocking: 'Render blocking', }; const str_ = i18n.i18n.registerUIStrings('panels/timeline/components/NetworkRequestTooltip.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class NetworkRequestTooltip extends HTMLElement { readonly #shadow = this.attachShadow({mode: 'open'}); #networkRequest?: Trace.Types.Events.SyntheticNetworkRequest|null; connectedCallback(): void { this.#shadow.adoptedStyleSheets = [networkRequestTooltipStyles]; this.#render(); } set networkRequest(networkRequest: Trace.Types.Events.SyntheticNetworkRequest) { if (this.#networkRequest === networkRequest) { return; } this.#networkRequest = networkRequest; this.#render(); } static renderPriorityValue(networkRequest: Trace.Types.Events.SyntheticNetworkRequest): Lit.TemplateResult { if (networkRequest.args.data.priority === networkRequest.args.data.initialPriority) { return html`${PerfUI.NetworkPriorities.uiLabelForNetworkPriority(networkRequest.args.data.priority)}`; } return html`${PerfUI.NetworkPriorities.uiLabelForNetworkPriority(networkRequest.args.data.initialPriority)} <devtools-icon name=${'arrow-forward'} class="priority"></devtools-icon> ${PerfUI.NetworkPriorities.uiLabelForNetworkPriority(networkRequest.args.data.priority)}`; } static renderTimings(networkRequest: Trace.Types.Events.SyntheticNetworkRequest): Lit.TemplateResult|null { const syntheticData = networkRequest.args.data.syntheticData; const queueing = (syntheticData.sendStartTime - networkRequest.ts) as Trace.Types.Timing.Micro; const requestPlusWaiting = (syntheticData.downloadStart - syntheticData.sendStartTime) as Trace.Types.Timing.Micro; const download = (syntheticData.finishTime - syntheticData.downloadStart) as Trace.Types.Timing.Micro; const waitingOnMainThread = (networkRequest.ts + networkRequest.dur - syntheticData.finishTime) as Trace.Types.Timing.Micro; const color = colorForNetworkRequest(networkRequest); const styleForWaiting = { backgroundColor: `color-mix(in srgb, ${color}, hsla(0, 100%, 100%, 0.8))`, }; const styleForDownloading = { backgroundColor: color, }; // The outside spans are transparent with a border on the outside edge. // The inside spans are 1px tall rectangles, vertically centered, with background color. // | // |---- // whisker-left-> | ^ horizontal const leftWhisker = html`<span class="whisker-left"> <span class="horizontal"></span> </span>`; const rightWhisker = html`<span class="whisker-right"> <span class="horizontal"></span> </span>`; return html` <div class="timings-row timings-row--duration"> <span class="indicator"></span> ${i18nString(UIStrings.duration)} <span class="time">${i18n.TimeUtilities.formatMicroSecondsTime(networkRequest.dur)}</span> </div> <div class="timings-row"> ${leftWhisker} ${i18nString(UIStrings.queuingAndConnecting)} <span class="time">${i18n.TimeUtilities.formatMicroSecondsTime(queueing)}</span> </div> <div class="timings-row"> <span class="indicator" style=${Lit.Directives.styleMap(styleForWaiting)}></span> ${i18nString(UIStrings.requestSentAndWaiting)} <span class="time">${i18n.TimeUtilities.formatMicroSecondsTime(requestPlusWaiting)}</span> </div> <div class="timings-row"> <span class="indicator" style=${Lit.Directives.styleMap(styleForDownloading)}></span> ${i18nString(UIStrings.contentDownloading)} <span class="time">${i18n.TimeUtilities.formatMicroSecondsTime(download)}</span> </div> <div class="timings-row"> ${rightWhisker} ${i18nString(UIStrings.waitingOnMainThread)} <span class="time">${i18n.TimeUtilities.formatMicroSecondsTime(waitingOnMainThread)}</span> </div> `; } #render(): void { if (!this.#networkRequest) { return; } const chipStyle = { backgroundColor: `${colorForNetworkRequest(this.#networkRequest)}`, }; const url = new URL(this.#networkRequest.args.data.url); // clang-format off const output = html` <div class="performance-card"> <div class="url">${Platform.StringUtilities.trimMiddle(url.href.replace(url.origin, ''), MAX_URL_LENGTH)}</div> <div class="url url--host">${url.origin.replace('https://', '')}</div> <div class="divider"></div> <div class="network-category"><span class="network-category-chip" style=${Lit.Directives.styleMap(chipStyle)}></span>${networkResourceCategory(this.#networkRequest)}</div> <div class="priority-row">${i18nString(UIStrings.priority)}: ${NetworkRequestTooltip.renderPriorityValue(this.#networkRequest)}</div> ${Trace.Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(this.#networkRequest) ? html`<div class="render-blocking"> ${i18nString(UIStrings.renderBlocking)} </div>` : Lit.nothing } <div class="divider"></div> ${NetworkRequestTooltip.renderTimings(this.#networkRequest)} </div> `; // clang-format on Lit.render(output, this.#shadow, {host: this}); } } declare global { interface HTMLElementTagNameMap { 'devtools-performance-network-request-tooltip': NetworkRequestTooltip; } } customElements.define('devtools-performance-network-request-tooltip', NetworkRequestTooltip);