chrome-devtools-frontend
Version:
Chrome DevTools UI
158 lines (138 loc) • 6.02 kB
text/typescript
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../../../../ui/legacy/components/data_grid/data_grid.js';
import '../../../../ui/kit/kit.js';
import * as Common from '../../../../core/common/common.js';
import * as i18n from '../../../../core/i18n/i18n.js';
import type * as Platform from '../../../../core/platform/platform.js';
import * as SDK from '../../../../core/sdk/sdk.js';
import type * as Protocol from '../../../../generated/protocol.js';
import * as UI from '../../../../ui/legacy/legacy.js';
import * as Lit from '../../../../ui/lit/lit.js';
import preloadingGridStyles from './preloadingGrid.css.js';
import {capitalizedAction, composedStatus, ruleSetTagOrLocationShort, sortOrder} from './PreloadingString.js';
const {PreloadingStatus} = SDK.PreloadingModel;
const UIStrings = {
/**
* @description Column header: Action of preloading (prefetch/prerender)
*/
action: 'Action',
/**
* @description Column header: A rule set of preloading
*/
ruleSet: 'Rule set',
/**
* @description Column header: Status of preloading attempt
*/
status: 'Status',
/**
* @description Status: Prerender failed, but prefetch is available
*/
prefetchFallbackReady: 'Prefetch fallback ready',
} as const;
const str_ = i18n.i18n.registerUIStrings('panels/application/preloading/components/PreloadingGrid.ts', UIStrings);
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
const {render, html, nothing, Directives: {styleMap}} = Lit;
// Shorten URL if a preloading attempt is same-origin.
function urlShort(row: PreloadingGridRow, securityOrigin: string|null): string {
const url = row.pipeline.getOriginallyTriggered().key.url;
return securityOrigin && url.startsWith(securityOrigin) ? url.slice(securityOrigin.length) : url;
}
export interface PreloadingGridRow {
id: string;
pipeline: SDK.PreloadingModel.PreloadPipeline;
ruleSets: Protocol.Preload.RuleSet[];
}
export interface ViewInput {
rows?: PreloadingGridRow[];
pageURL?: Platform.DevToolsPath.UrlString;
onSelect?: ({rowId}: {rowId: string}) => void;
}
type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
export const PRELOADING_GRID_DEFAULT_VIEW: View = (input, _output, target): void => {
if (!input.rows || input.pageURL === undefined) {
render(nothing, target);
return;
}
const {rows, pageURL} = input;
const securityOrigin = pageURL === '' ? null : (new Common.ParsedURL.ParsedURL(pageURL)).securityOrigin();
// Disabled until https://crbug.com/1079231 is fixed.
// clang-format off
render(html`
<style>${preloadingGridStyles}</style>
<div class="preloading-container">
<devtools-data-grid striped>
<table>
<tr>
<th id="url" weight="40" sortable>${i18n.i18n.lockedString('URL')}</th>
<th id="action" weight="15" sortable>${i18nString(UIStrings.action)}</th>
<th id="rule-set" weight="20" sortable>${i18nString(UIStrings.ruleSet)}</th>
<th id="status" weight="40" sortable>${i18nString(UIStrings.status)}</th>
</tr>
${rows.map(row => {
const attempt = row.pipeline.getOriginallyTriggered();
const prefetchStatus = row.pipeline.getPrefetch()?.status;
const prerenderStatus = row.pipeline.getPrerender()?.status;
const hasWarning =
(prerenderStatus === PreloadingStatus.FAILURE &&
(prefetchStatus === PreloadingStatus.READY || prefetchStatus === PreloadingStatus.SUCCESS));
const hasError = row.pipeline.getOriginallyTriggered().status === PreloadingStatus.FAILURE;
return html`<tr @select=${() => input.onSelect?.({rowId: row.id})}>
<td title=${attempt.key.url}>${urlShort(row, securityOrigin)}</td>
<td>${capitalizedAction(attempt.action)}</td>
<td>${row.ruleSets.length === 0 ? '' : ruleSetTagOrLocationShort(row.ruleSets[0], pageURL)}</td>
<td data-value=${sortOrder(attempt)}>
<div style=${styleMap({color: hasWarning ? 'var(--sys-color-orange-bright)'
: hasError ? 'var(--sys-color-error)'
: 'var(--sys-color-on-surface)'})}>
${(hasError || hasWarning) ? html`
<devtools-icon
name=${hasWarning ? 'warning-filled' : 'cross-circle-filled'}
class='medium'
style=${styleMap({
'vertical-align': 'sub',
})}
></devtools-icon>` : ''}
${hasWarning ? i18nString(UIStrings.prefetchFallbackReady) : composedStatus(attempt)}
</div>
</td>
</tr>`;
})}
</table>
</devtools-data-grid>
</div>
`, target);
}; // clang-format on
/** Grid component to show prerendering attempts. **/
export class PreloadingGrid extends UI.Widget.VBox {
#view: View;
#rows?: PreloadingGridRow[];
#pageURL?: Platform.DevToolsPath.UrlString;
#onSelect?: ({rowId}: {rowId: string}) => void;
constructor(view?: View) {
super();
this.#view = view ?? PRELOADING_GRID_DEFAULT_VIEW;
this.requestUpdate();
}
set rows(rows: PreloadingGridRow[]) {
this.#rows = rows;
this.requestUpdate();
}
set pageURL(pageURL: Platform.DevToolsPath.UrlString) {
this.#pageURL = pageURL;
this.requestUpdate();
}
set onSelect(onSelect: ({rowId}: {rowId: string}) => void) {
this.#onSelect = onSelect;
this.requestUpdate();
}
override performUpdate(): void {
const viewInput: ViewInput = {
rows: this.#rows,
pageURL: this.#pageURL,
onSelect: this.#onSelect?.bind(this),
};
this.#view(viewInput, undefined, this.contentElement);
}
}