UNPKG

chrome-devtools-frontend

Version:
81 lines (68 loc) 3.09 kB
// Copyright 2024 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 TextUtils from '../../models/text_utils/text_utils.js'; import {Events, type EventSourceMessage, type NetworkRequest} from './NetworkRequest.js'; import {ServerSentEventsParser} from './ServerSentEventsProtocol.js'; /** * Server sent events only arrive via CDP (Explicit Network.eventSourceMessageReceived) when * the page uses "EventSource" in the code. * * If the page manually uses 'fetch' or XHR we have to do the protocol parsing * ourselves. * * `ServerSentEvents` is a small helper class that manages this distinction for a specific * request, stores the event data and sends out "EventSourceMessageAdded" events for a request. */ export class ServerSentEvents { readonly #request: NetworkRequest; readonly #parser?: ServerSentEventsParser; // In the case where we parse the events ourselves we use the time of the last 'dataReceived' // event for all the events that come out of the corresponding chunk of data. #lastDataReceivedTime = 0; readonly #eventSourceMessages: EventSourceMessage[] = []; constructor(request: NetworkRequest, parseFromStreamedData: boolean) { this.#request = request; // Only setup parsing if we don't get the events over CDP directly. if (parseFromStreamedData) { this.#lastDataReceivedTime = request.pseudoWallTime(request.startTime); this.#parser = new ServerSentEventsParser(this.#onParserEvent.bind(this), request.charset() ?? undefined); // Get the streaming content and add the already received bytes if someone else started // the streaming earlier. void this.#request.requestStreamingContent().then(streamingContentData => { if (!TextUtils.StreamingContentData.isError(streamingContentData)) { void this.#parser?.addBase64Chunk(streamingContentData.content().base64); streamingContentData.addEventListener( TextUtils.StreamingContentData.Events.CHUNK_ADDED, ({data: {chunk}}) => { this.#lastDataReceivedTime = request.pseudoWallTime(request.endTime); void this.#parser?.addBase64Chunk(chunk); }); } }); } } get eventSourceMessages(): readonly EventSourceMessage[] { return this.#eventSourceMessages; } /** Forwarded Network.eventSourceMessage received */ onProtocolEventSourceMessageReceived(eventName: string, data: string, eventId: string, time: number): void { this.#recordMessageAndDispatchEvent({ eventName, eventId, data, time, }); } #onParserEvent(eventName: string, data: string, eventId: string): void { this.#recordMessageAndDispatchEvent({ eventName, eventId, data, time: this.#lastDataReceivedTime, }); } #recordMessageAndDispatchEvent(message: EventSourceMessage): void { this.#eventSourceMessages.push(message); this.#request.dispatchEventToListeners(Events.EVENT_SOURCE_MESSAGE_ADDED, message); } }