UNPKG

chrome-devtools-frontend

Version:
220 lines (198 loc) 7.37 kB
// Copyright 2025 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Common from '../../core/common/common.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as TextUtils from '../../core/text_utils/text_utils.js'; import * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js'; import * as Lit from '../../ui/lit/lit.js'; import * as VisualLogging from '../../ui/visual_logging/visual_logging.js'; import {BinaryResourceView} from './BinaryResourceView.js'; import {DataGridItem, defaultHeaderTemplate, ResourceChunkView} from './ResourceChunkView.js'; const { html, } = Lit; const UIStrings = { /** * @description Text in Event Source Messages View of the Network panel */ data: 'Data', /** * @description Text in Messages View of the Network panel */ length: 'Length', /** * @description Text that refers to the time */ time: 'Time', /** * @description Text in Messages View of the Network panel */ address: 'Address', /** * @description Text in Messages View of the Network panel */ port: 'Port', /** * @description Data grid name for Direct Socket Chunk data grids */ directSocketChunk: 'Direct Socket Chunk', /** * @description Example for placeholder text. Note: "(direct)?socket)" is an example code and should not be translated. */ filterUsingRegex: 'Filter using regex (example: `(direct)?socket)`', } as const; const str_ = i18n.i18n.registerUIStrings('panels/network/ResourceDirectSocketChunkView.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_); // clang-format off function udpBoundHeaderTemplate(): Lit.TemplateResult { return html` <tr> <th id="data" weight="63">${i18nLazyString(UIStrings.data)}</th> <th id="address" align="right" weight="15">${i18nLazyString(UIStrings.address)}</th> <th id="port" align="right" weight="10">${i18nLazyString(UIStrings.port)}</th> <th id="length" align="right" weight="5">${i18nLazyString(UIStrings.length)}</th> <th id="time" sortable sort="ascending" weight="7">${i18nLazyString(UIStrings.time)}</th> </tr>`; } // clang-format on export class ResourceDirectSocketChunkView extends ResourceChunkView<SDK.NetworkRequest.DirectSocketChunk> { override get headerTemplate(): Lit.TemplateResult { if (this.request.directSocketInfo?.type === SDK.NetworkRequest.DirectSocketType.UDP_BOUND) { return udpBoundHeaderTemplate(); } return defaultHeaderTemplate(); } constructor(request: SDK.NetworkRequest.NetworkRequest) { super(request, 'network-direct-socket-chunk-filter', 'resource-direct-socket-chunk-split-view-state', i18nString(UIStrings.directSocketChunk), i18nString(UIStrings.filterUsingRegex), {jslog: `${VisualLogging.pane('direct-socket-messages').track({resize: true})}`}); } override getRequestChunks(): SDK.NetworkRequest.DirectSocketChunk[] { return this.request.directSocketChunks(); } override chunkFilter(chunk: SDK.NetworkRequest.DirectSocketChunk): boolean { if (this.filterType && chunk.type !== this.filterType) { return false; } return !this.filterRegex || this.filterRegex.test(chunk.data); } override createGridItem(chunk: SDK.NetworkRequest.DirectSocketChunk): DataGridItem { return new ResourceChunkNode( chunk, this.request.directSocketInfo?.type === SDK.NetworkRequest.DirectSocketType.UDP_BOUND); } override wasShown(): void { super.wasShown(); this.requestUpdate(); this.request.addEventListener( SDK.NetworkRequest.Events.DIRECTSOCKET_CHUNK_ADDED, this.onDirectSocketChunkAdded, this); } override willHide(): void { super.willHide(); this.request.removeEventListener( SDK.NetworkRequest.Events.DIRECTSOCKET_CHUNK_ADDED, this.onDirectSocketChunkAdded, this); } private onDirectSocketChunkAdded(event: Common.EventTarget.EventTargetEvent<SDK.NetworkRequest.DirectSocketChunk>): void { this.chunkAdded(event.data); } override getColumns(): DataGrid.DataGrid.ColumnDescriptor[] { if (this.request.directSocketInfo?.type === SDK.NetworkRequest.DirectSocketType.UDP_BOUND) { return [ { id: 'data', title: i18nString(UIStrings.data), sortable: false, weight: 63, }, { id: 'address', title: i18nString(UIStrings.address), sortable: false, align: DataGrid.DataGrid.Align.RIGHT, weight: 15, }, { id: 'port', title: i18nString(UIStrings.port), sortable: false, align: DataGrid.DataGrid.Align.RIGHT, weight: 10, }, { id: 'length', title: i18nString(UIStrings.length), sortable: false, align: DataGrid.DataGrid.Align.RIGHT, weight: 5, }, { id: 'time', title: i18nString(UIStrings.time), sortable: true, weight: 7, }, ]; } return super.getColumns(); } } class ResourceChunkNode extends DataGridItem { #binaryView: BinaryResourceView|null = null; readonly chunk: SDK.NetworkRequest.DirectSocketChunk; override readonly isTextFrame = false; override readonly data: Record<string, string|HTMLElement>; override readonly cssClass: string; constructor(chunk: SDK.NetworkRequest.DirectSocketChunk, boundSocket: boolean) { super(); let description: string; const length = i18n.ByteUtilities.bytesToString(Platform.StringUtilities.base64ToSize(chunk.data)); const maxDisplayLen = 30; if (chunk.data.length > maxDisplayLen) { description = chunk.data.substring(0, maxDisplayLen) + '…'; } else { description = chunk.data; } if (boundSocket) { this.data = { data: description, address: chunk.remoteAddress ?? '', port: chunk.remotePort?.toString() ?? '', length, }; } else { this.data = { data: description, length, }; } let cssClass = ''; if (chunk.type === SDK.NetworkRequest.DirectSocketChunkType.SEND) { cssClass = 'resource-chunk-view-row-send'; } else if (chunk.type === SDK.NetworkRequest.DirectSocketChunkType.RECEIVE) { cssClass = 'resource-chunk-view-row-receive'; } this.cssClass = cssClass; this.chunk = chunk; } override dataText(): string { return this.chunk.data; } override binaryView(): BinaryResourceView|null { if (!this.#binaryView) { if (this.dataText().length > 0) { this.#binaryView = new BinaryResourceView( TextUtils.StreamingContentData.StreamingContentData.from( new TextUtils.ContentData.ContentData(this.dataText(), true, 'application/octet-stream')), Platform.DevToolsPath.EmptyUrlString, Common.ResourceType.resourceTypes.DirectSocket); } } return this.#binaryView; } override getTime(): number { return this.chunk.timestamp; } }