{"version":3,"file":"ExtensionTraceDataHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ExtensionTraceDataHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {HandlerName} from './types.js';\nimport {data as userTimingsData} from './UserTimingsHandler.js';\n\nconst extensionTrackEntries: Types.Extensions.SyntheticExtensionTrackEntry[] = [];\nconst extensionTrackData: Types.Extensions.ExtensionTrackData[] = [];\nconst extensionMarkers: Types.Extensions.SyntheticExtensionMarker[] = [];\nconst entryToNode = new Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>();\nconst timeStampByName = new Map<string, Types.Events.ConsoleTimeStamp>();\n\nconst syntheticConsoleEntriesForTimingsTrack: Types.Events.SyntheticConsoleTimeStamp[] = [];\n\nexport interface ExtensionTraceData {\n  extensionTrackData: readonly Types.Extensions.ExtensionTrackData[];\n  extensionMarkers: readonly Types.Extensions.SyntheticExtensionMarker[];\n  // TODO(andoli): Can we augment Renderer's entryToNode instead? To avoid the split of TimelineUIUtils's getEventSelfTime()?\n  entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>;\n  syntheticConsoleEntriesForTimingsTrack: Types.Events.SyntheticConsoleTimeStamp[];\n}\n\nexport function handleEvent(_event: Types.Events.Event): void {\n  // Implementation not needed because data is sourced from UserTimingsHandler\n}\n\nexport function reset(): void {\n  extensionTrackEntries.length = 0;\n  syntheticConsoleEntriesForTimingsTrack.length = 0;\n  extensionTrackData.length = 0;\n  extensionMarkers.length = 0;\n  entryToNode.clear();\n  timeStampByName.clear();\n}\n\nexport async function finalize(): Promise<void> {\n  createExtensionFlameChartEntries();\n}\n\nfunction createExtensionFlameChartEntries(): void {\n  const pairedMeasures: readonly Types.Events.SyntheticUserTimingPair[] = userTimingsData().performanceMeasures;\n  const marks: readonly Types.Events.PerformanceMark[] = userTimingsData().performanceMarks;\n  const mergedRawExtensionEvents = Helpers.Trace.mergeEventsInOrder(pairedMeasures, marks);\n\n  extractPerformanceAPIExtensionEntries(mergedRawExtensionEvents);\n  extractConsoleAPIExtensionEntries();\n  // extensionTrackEntries is filled by the above two calls.\n  Helpers.Trace.sortTraceEventsInPlace(extensionTrackEntries);\n  Helpers.Extensions.buildTrackDataFromExtensionEntries(extensionTrackEntries, extensionTrackData, entryToNode);\n}\n\n/**\n * Extracts extension entries from console.timeStamp events.\n *\n * Entries are built by pairing `console.timeStamp` events based on\n * their names. When a `console.timeStamp` event includes a `start`\n * argument (and optionally an `end` argument), it attempts to find\n * previously recorded `console.timeStamp` events with names matching\n * the `start` and `end` values. These matching events are then used to\n * determine the start and end times of the new entry.\n *\n * If a `console.timeStamp` event includes data for a custom track\n * (specified by the `track` argument), an extension track entry is\n * created and added to the `extensionTrackEntries` array. These entries\n * are used to visualize custom tracks in the Performance panel.\n *\n * If a `console.timeStamp` event includes data for a custom track\n * (specified by the `track` argument), an extension track entry is\n * created and added to the `extensionTrackEntries` array. These entries\n * are used to visualize custom tracks in the Performance panel.\n *\n * If a `console.timeStamp` event does not specify a custom track but\n * includes a start and/or end time (referencing other\n * `console.timeStamp` names), a synthetic console time stamp entry is\n * created and added to the `syntheticConsoleEntriesForTimingsTrack`\n * array. These entries are displayed in the \"Timings\" track.\n */\nexport function extractConsoleAPIExtensionEntries(): void {\n  const consoleTimeStamps: readonly Types.Events.ConsoleTimeStamp[] = userTimingsData().timestampEvents;\n  for (const currentTimeStamp of consoleTimeStamps) {\n    if (!currentTimeStamp.args.data) {\n      continue;\n    }\n    const timeStampName = String(currentTimeStamp.args.data.name ?? currentTimeStamp.args.data.message);\n    timeStampByName.set(timeStampName, currentTimeStamp);\n    const extensionData = extensionDataInConsoleTimeStamp(currentTimeStamp);\n    const start = currentTimeStamp.args.data.start;\n    const end = currentTimeStamp.args.data.end;\n    if (!extensionData && !start && !end) {\n      continue;\n    }\n    // If the start or end is a number, it's assumed to be a timestamp\n    // from the tracing clock, so we use that directly, otherwise we\n    // assume it's the label of a previous console timestamp, in which\n    // case we use its corresponding timestamp.\n    const startTimeStamp =\n        typeof start === 'number' ? Types.Timing.Micro(start) : timeStampByName.get(String(start))?.ts;\n    const endTimeStamp = typeof end === 'number' ? Types.Timing.Micro(end) : timeStampByName.get(String(end))?.ts;\n    if (endTimeStamp !== undefined && startTimeStamp === undefined) {\n      // Invalid data\n      continue;\n    }\n    const entryStartTime = startTimeStamp ?? currentTimeStamp.ts;\n    const entryEndTime = endTimeStamp ?? currentTimeStamp.ts;\n    if (extensionData) {\n      const unregisteredExtensionEntry: Omit<Types.Extensions.SyntheticExtensionTrackEntry, '_tag'> = {\n        ...currentTimeStamp,\n        name: timeStampName,\n        cat: 'devtools.extension',\n        args: extensionData,\n        rawSourceEvent: currentTimeStamp,\n        dur: Types.Timing.Micro(entryEndTime - entryStartTime),\n        ts: entryStartTime,\n        ph: Types.Events.Phase.COMPLETE,\n      };\n      const extensionEntry =\n          Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n              .registerSyntheticEvent<Types.Extensions.SyntheticExtensionTrackEntry>(unregisteredExtensionEntry);\n      extensionTrackEntries.push(extensionEntry);\n      continue;\n    }\n    // If no extension data is found in the entry (no custom track name\n    // was passed), but the entry has a duration. we still save it here\n    // to be added in the timings track. Note that timings w/o duration\n    // and extension data are already handled by the UserTimingsHandler.\n    const unregisteredSyntheticTimeStamp: Omit<Types.Events.SyntheticConsoleTimeStamp, '_tag'> = {\n      ...currentTimeStamp,\n      name: timeStampName,\n      cat: 'disabled-by-default-v8.inspector',\n      ph: Types.Events.Phase.COMPLETE,\n      ts: entryStartTime,\n      dur: Types.Timing.Micro(entryEndTime - entryStartTime),\n      rawSourceEvent: currentTimeStamp\n    };\n    const syntheticTimeStamp =\n        Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n            .registerSyntheticEvent<Types.Events.SyntheticConsoleTimeStamp>(unregisteredSyntheticTimeStamp);\n    syntheticConsoleEntriesForTimingsTrack.push(syntheticTimeStamp);\n  }\n}\n\n/**\n * Extracts extension entries from Performance API events (marks and\n * measures).\n * It specifically looks for events that contain extension-specific data\n * within their `detail` property.\n *\n * If an event's `detail` property can be parsed as a JSON object and\n * contains a `devtools` field with a valid extension payload, a\n * synthetic extension entry is created. The type of extension entry\n * created depends on the payload:\n *\n * - If the payload conforms to `ExtensionPayloadMarker`, a\n *   `SyntheticExtensionMarker` is created and added to the\n *   `extensionMarkers` array. These markers represent single points in\n *   time.\n * - If the payload conforms to `ExtensionPayloadTrackEntry`, a\n *   `SyntheticExtensionTrackEntry` is created and added to the\n *   `extensionTrackEntries` array. These entries represent events with\n *   a duration and are displayed on custom tracks in the Performance\n *   panel.\n *\n * **Note:** Only events with a `detail` property that contains valid\n * extension data are processed. Other `performance.mark` and\n * `performance.measure` events are ignored.\n *\n * @param timings An array of `SyntheticUserTimingPair` or\n *                `PerformanceMark` events, typically obtained from the\n *                `UserTimingsHandler`.\n */\nexport function extractPerformanceAPIExtensionEntries(\n    timings: Array<Types.Events.SyntheticUserTimingPair|Types.Events.PerformanceMark>): void {\n  for (const timing of timings) {\n    const extensionPayload = extensionDataInPerformanceTiming(timing);\n    if (!extensionPayload) {\n      // Not an extension user timing.\n      continue;\n    }\n\n    const extensionSyntheticEntry = {\n      name: timing.name,\n      ph: Types.Extensions.isExtensionPayloadMarker(extensionPayload) ? Types.Events.Phase.INSTANT :\n                                                                        Types.Events.Phase.COMPLETE,\n      pid: timing.pid,\n      tid: timing.tid,\n      ts: timing.ts,\n      dur: timing.dur as Types.Timing.Micro,\n      cat: 'devtools.extension',\n      args: extensionPayload,\n      rawSourceEvent: Types.Events.isSyntheticUserTiming(timing) ? timing.rawSourceEvent : timing,\n    };\n\n    if (Types.Extensions.isExtensionPayloadMarker(extensionPayload)) {\n      const extensionMarker =\n          Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n              .registerSyntheticEvent<Types.Extensions.SyntheticExtensionMarker>(\n                  extensionSyntheticEntry as Omit<Types.Extensions.SyntheticExtensionMarker, '_tag'>);\n      extensionMarkers.push(extensionMarker);\n      continue;\n    }\n\n    if (Types.Extensions.isExtensionPayloadTrackEntry(extensionSyntheticEntry.args)) {\n      const extensionTrackEntry =\n          Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n              .registerSyntheticEvent<Types.Extensions.SyntheticExtensionTrackEntry>(\n                  extensionSyntheticEntry as Omit<Types.Extensions.SyntheticExtensionTrackEntry, '_tag'>);\n      extensionTrackEntries.push(extensionTrackEntry);\n      continue;\n    }\n  }\n}\n\nexport function extensionDataInPerformanceTiming(\n    timing: Types.Events.SyntheticUserTimingPair|Types.Events.PerformanceMark): Types.Extensions.ExtensionDataPayload|\n    null {\n  const timingDetail =\n      Types.Events.isPerformanceMark(timing) ? timing.args.data?.detail : timing.args.data.beginEvent.args.detail;\n  if (!timingDetail) {\n    return null;\n  }\n  try {\n    // Attempt to parse the detail as an object that might be coming from a\n    // DevTools Perf extension.\n    // Wrapped in a try-catch because timingDetail might either:\n    // 1. Not be `json.parse`-able (it should, but just in case...)\n    // 2.Not be an object - in which case the `in` check will error.\n    // If we hit either of these cases, we just ignore this mark and move on.\n    const detailObj = JSON.parse(timingDetail);\n    if (!('devtools' in detailObj)) {\n      return null;\n    }\n    if (!Types.Extensions.isValidExtensionPayload(detailObj.devtools)) {\n      return null;\n    }\n    return detailObj.devtools;\n  } catch {\n    // No need to worry about this error, just discard this event and don't\n    // treat it as having any useful information for the purposes of extensions\n    return null;\n  }\n}\n/**\n * Extracts extension data from a `console.timeStamp` event.\n *\n * Checks if a `console.timeStamp` event contains data intended for\n * creating a custom track entry in the DevTools Performance panel. It\n * specifically looks for a `track` argument within the event's data.\n *\n * If a `track` argument is present (and not an empty string), the\n * function constructs an `ExtensionTrackEntryPayload` object containing\n * the track name, an optional color, an optional track group. This\n * payload is then used to create a `SyntheticExtensionTrackEntry`.\n *\n * **Note:** The `color` argument is optional and its type is validated\n * against a predefined palette (see\n * `ExtensionUI::extensionEntryColor`).\n *\n * @param timeStamp The `ConsoleTimeStamp` event to extract data from.\n * @return An `ExtensionTrackEntryPayload` object if the event contains\n *         valid extension data for a track entry, or `null` otherwise.\n */\nexport function extensionDataInConsoleTimeStamp(timeStamp: Types.Events.ConsoleTimeStamp):\n    Types.Extensions.ExtensionTrackEntryPayload|null {\n  if (!timeStamp.args.data) {\n    return null;\n  }\n  const trackName = timeStamp.args.data.track;\n  if (trackName === '' || trackName === undefined) {\n    return null;\n  }\n  return {\n    // the color is defaulted to primary if it's value isn't one from\n    // the defined palette (see ExtensionUI::extensionEntryColor) so\n    // we don't need to check the value is valid here.\n    color: String(timeStamp.args.data.color) as Types.Extensions.ExtensionTrackEntryPayload['color'],\n    track: String(trackName),\n    dataType: 'track-entry',\n    trackGroup: timeStamp.args.data.trackGroup !== undefined ? String(timeStamp.args.data.trackGroup) : undefined\n  };\n}\n\nexport function data(): ExtensionTraceData {\n  return {\n    entryToNode,\n    extensionTrackData,\n    extensionMarkers,\n    syntheticConsoleEntriesForTimingsTrack,\n  };\n}\n\nexport function deps(): HandlerName[] {\n  return ['UserTimings'];\n}\n"]}