| // Copyright 2023 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 i18n from '../../core/i18n/i18n.js'; |
| import type * as Platform from '../../core/platform/platform.js'; |
| |
| import * as Handlers from './handlers/handlers.js'; |
| import * as Helpers from './helpers/helpers.js'; |
| import * as Types from './types/types.js'; |
| |
| const UIStrings = { |
| /** |
| * @description Category in the Summary view of the Performance panel to indicate time spent to load resources |
| */ |
| loading: 'Loading', |
| /** |
| * @description Text in Timeline for the Experience title |
| */ |
| experience: 'Experience', |
| /** |
| * @description Category in the Summary view of the Performance panel to indicate time spent in script execution |
| */ |
| scripting: 'Scripting', |
| /** |
| * @description Category in the Summary view of the Performance panel to indicate time spent in rendering the web page |
| */ |
| rendering: 'Rendering', |
| /** |
| * @description Category in the Summary view of the Performance panel to indicate time spent to visually represent the web page |
| */ |
| painting: 'Painting', |
| /** |
| * @description Event category in the Performance panel for time spent in the GPU |
| */ |
| gpu: 'GPU', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| async: 'Async', |
| /** |
| * @description Category in the Summary view of the Performance panel to indicate time spent in the rest of the system |
| */ |
| system: 'System', |
| /** |
| * @description Category in the Summary view of the Performance panel to indicate idle time |
| */ |
| idle: 'Idle', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| task: 'Task', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| consoleTaskRun: 'Run console task', |
| /** |
| * @description Text for other types of items |
| */ |
| other: 'Other', |
| /** |
| * @description Text that refers to the animation of the web page |
| */ |
| animation: 'Animation', |
| /** |
| * @description Text that refers to some events |
| */ |
| event: 'Event', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| requestMainThreadFrame: 'Request main thread frame', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| frameStart: 'Frame start', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| onMessage: 'On message', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| schedulePostMessage: 'Schedule postMessage', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| messaging: 'Messaging', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| frameStartMainThread: 'Frame start (main thread)', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| drawFrame: 'Draw frame', |
| /** |
| * @description Noun for an event in the Performance panel. This marks time |
| * spent in an operation that only happens when the profiler is active. |
| */ |
| profilingOverhead: 'Profiling overhead', |
| /** |
| * @description The process the browser uses to determine a target element for a |
| *pointer event. Typically, this is determined by considering the pointer's |
| *location and also the visual layout of elements on the screen. |
| */ |
| hitTest: 'Hit test', |
| /** |
| * @description Noun for an event in the Performance panel. The browser has decided |
| *that the styles for some elements need to be recalculated and scheduled that |
| *recalculation process at some time in the future. |
| */ |
| scheduleStyleRecalculation: 'Schedule style recalculation', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| recalculateStyle: 'Recalculate style', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| invalidateLayout: 'Invalidate Layout', |
| /** |
| * @description Noun for an event in the Performance panel. Layerize is a step |
| *where we calculate which layers to create. |
| */ |
| layerize: 'Layerize', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| layout: 'Layout', |
| /** |
| * @description Noun for an event in the Performance panel. Paint setup is a |
| *step before the 'Paint' event. A paint event is when the browser draws pixels |
| *to the screen. This step is the setup beforehand. |
| */ |
| paintSetup: 'Paint setup', |
| /** |
| * @description Noun for a paint event in the Performance panel, where an image |
| *was being painted. A paint event is when the browser draws pixels to the |
| *screen, in this case specifically for an image in a website. |
| */ |
| paintImage: 'Paint image', |
| /** |
| * @description Noun for an event in the Performance panel. Pre-paint is a |
| *step before the 'Paint' event. A paint event is when the browser records the |
| *instructions for drawing the page. This step is the setup beforehand. |
| */ |
| prePaint: 'Pre-paint', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| updateLayer: 'Update layer', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| updateLayerTree: 'Update layer tree', |
| /** |
| * @description Noun for a paint event in the Performance panel. A paint event is when the browser draws pixels to the screen. |
| */ |
| paint: 'Paint', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| rasterizePaint: 'Rasterize paint', |
| /** |
| * @description The action to scroll |
| */ |
| scroll: 'Scroll', |
| /** |
| * @description Noun for an event in the Performance panel. Commit is a step |
| *where we send (also known as "commit") layers to the compositor thread. This |
| *step follows the "Layerize" step which is what calculates which layers to |
| *create. |
| */ |
| commit: 'Commit', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| compositeLayers: 'Composite layers', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| computeIntersections: 'Compute intersections', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| parseHtml: 'Parse HTML', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| parseStylesheet: 'Parse stylesheet', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| installTimer: 'Install timer', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| removeTimer: 'Remove timer', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| timerFired: 'Timer fired', |
| /** |
| * @description Text for an event. Shown in the timeline in the Performance panel. |
| * XHR refers to XmlHttpRequest, a Web API. This particular Web API has a property |
| * named 'readyState' (https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState). When |
| * the 'readyState' property changes the text is shown. |
| */ |
| xhrReadyStateChange: '`XHR` `readyState` change', |
| /** |
| * @description Text for an event. Shown in the timeline in the Performance panel. |
| * XHR refers to XmlHttpRequest, a Web API. (see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) |
| * The text is shown when a XmlHttpRequest load event happens on the inspected page. |
| */ |
| xhrLoad: '`XHR` load', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| compileScript: 'Compile script', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| cacheScript: 'Cache script code', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| compileCode: 'Compile code', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| optimizeCode: 'Optimize code', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| evaluateScript: 'Evaluate script', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| compileModule: 'Compile module', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| cacheModule: 'Cache module code', |
| /** |
| * @description Text for an event. Shown in the timeline in the Performance panel. |
| * "Module" refers to JavaScript modules: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules |
| * JavaScript modules are a way to organize JavaScript code. |
| * "Evaluate" is the phase when the JavaScript code of a module is executed. |
| */ |
| evaluateModule: 'Evaluate module', |
| /** |
| * @description Noun indicating that a compile task (type: streaming) happened. |
| */ |
| streamingCompileTask: 'Streaming compile task', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| waitingForNetwork: 'Waiting for network', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| parseAndCompile: 'Parse and compile', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel. |
| * "Code Cache" refers to JavaScript bytecode cache: https://v8.dev/blog/code-caching-for-devs |
| * "Deserialize" refers to the process of reading the code cache. |
| */ |
| deserializeCodeCache: 'Deserialize code cache', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| streamingWasmResponse: 'Streaming Wasm response', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| compiledWasmModule: 'Compiled Wasm module', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| cachedWasmModule: 'Cached Wasm module', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| wasmModuleCacheHit: 'Wasm module cache hit', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| wasmModuleCacheInvalid: 'Wasm module cache invalid', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| frameStartedLoading: 'Frame started loading', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| onloadEvent: 'Onload event', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| domcontentloadedEvent: 'DOMContentLoaded event', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| firstPaint: 'First Paint', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| firstContentfulPaint: 'First Contentful Paint', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| largestContentfulPaint: 'Largest Contentful Paint', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| softLargestContentfulPaint: 'Soft Largest Contentful Paint', |
| /** |
| * @description Text for timestamps of items |
| */ |
| timestamp: 'Timestamp', |
| /** |
| * @description Noun for a 'time' event that happens in the Console (a tool in |
| * DevTools). The user can trigger console time events from their code, and |
| * they will show up in the Performance panel. Time events are used to measure |
| * the duration of something, e.g. the user will emit two time events at the |
| * start and end of some interesting task. |
| */ |
| consoleTime: 'Console time', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| userTiming: 'User timing', |
| /** |
| * @description Name for an event shown in the Performance panel. When a network |
| * request is about to be sent by the browser, the time is recorded and DevTools |
| * is notified that a network request will be sent momentarily. |
| */ |
| willSendRequest: 'Will send request', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| sendRequest: 'Send request', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| receiveResponse: 'Receive response', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| finishLoading: 'Finish loading', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| receiveData: 'Receive data', |
| /** |
| * @description Event category in the Performance panel for time spent to execute microtasks in JavaScript |
| */ |
| runMicrotasks: 'Run microtasks', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| functionCall: 'Function call', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| gcEvent: 'GC event', |
| /** |
| * @description Event category in the Performance panel for time spent to perform a full Garbage Collection pass |
| */ |
| majorGc: 'Major GC', |
| /** |
| * @description Event category in the Performance panel for time spent to perform a quick Garbage Collection pass |
| */ |
| minorGc: 'Minor GC', |
| /** |
| * @description Text for the request animation frame event |
| */ |
| requestAnimationFrame: 'Request animation frame', |
| /** |
| * @description Text to cancel the animation frame |
| */ |
| cancelAnimationFrame: 'Cancel animation frame', |
| /** |
| * @description Text for the event that an animation frame is fired |
| */ |
| animationFrameFired: 'Animation frame fired', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| requestIdleCallback: 'Request idle callback', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| cancelIdleCallback: 'Cancel idle callback', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| fireIdleCallback: 'Fire idle callback', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| createWebsocket: 'Create WebSocket', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| sendWebsocketHandshake: 'Send WebSocket handshake', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| receiveWebsocketHandshake: 'Receive WebSocket handshake', |
| /** |
| * @description Text in Timeline Flame Chart Data Provider of the Performance panel |
| */ |
| wsMessageReceived: 'Receive WebSocket message', |
| /** |
| * @description Text in Timeline Flame Chart Data Provider of the Performance panel |
| */ |
| wsMessageSent: 'Send WebSocket message', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| destroyWebsocket: 'Destroy WebSocket', |
| /** |
| * @description Event category in the Performance panel for time spent in the embedder of the WebView |
| */ |
| embedderCallback: 'Embedder callback', |
| /** |
| * @description Event category in the Performance panel for time spent decoding an image |
| */ |
| imageDecode: 'Image decode', |
| /** |
| * @description Event category in the Performance panel for time spent to perform Garbage Collection for the Document Object Model |
| */ |
| domGc: 'DOM GC', |
| /** |
| * @description Event category in the Performance panel for time spent to perform Garbage Collection for C++: https://chromium.googlesource.com/v8/v8/+/main/include/cppgc/README.md |
| */ |
| cppGc: 'C++ GC', |
| /** |
| * @description Event category in the Performance panel for time spent to perform encryption |
| */ |
| encrypt: 'Encrypt', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| encryptReply: 'Encrypt reply', |
| /** |
| * @description Event category in the Performance panel for time spent to perform decryption |
| */ |
| decrypt: 'Decrypt', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| decryptReply: 'Decrypt reply', |
| /** |
| * @description Noun phrase meaning 'the browser was preparing the digest'. |
| * Digest: https://developer.mozilla.org/en-US/docs/Glossary/Digest |
| */ |
| digest: 'Digest', |
| /** |
| * @description Noun phrase meaning 'the browser was preparing the digest |
| *reply'. Digest: https://developer.mozilla.org/en-US/docs/Glossary/Digest |
| */ |
| digestReply: 'Digest reply', |
| /** |
| * @description The 'sign' stage of a web crypto event. Shown when displaying what the website was doing at a particular point in time. |
| */ |
| sign: 'Sign', |
| /** |
| * @description Noun phrase for an event of the Web Crypto API. The event is recorded when the signing process is concluded. |
| * Signature: https://developer.mozilla.org/en-US/docs/Glossary/Signature/Security |
| */ |
| signReply: 'Sign reply', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| verify: 'Verify', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| verifyReply: 'Verify reply', |
| /** |
| * @description Text in Timeline UIUtils of the Performance panel |
| */ |
| asyncTask: 'Async task', |
| /** |
| * @description Text in Timeline for Layout Shift records |
| */ |
| layoutShift: 'Layout shift', |
| /** |
| * @description Text in Timeline for Layout Shift records |
| */ |
| layoutShiftCluster: 'Layout shift cluster', |
| /** |
| * @description Text in Timeline for an Event Timing record |
| */ |
| eventTiming: 'Event timing', |
| /** |
| * @description Event category in the Performance panel for JavaScript nodes in CPUProfile |
| */ |
| jsFrame: 'JS frame', |
| /** |
| * @description Text in UIDevtools Utils of the Performance panel |
| */ |
| rasterizing: 'Rasterizing', |
| /** |
| * @description Text in UIDevtools Utils of the Performance panel |
| */ |
| drawing: 'Drawing', |
| /** |
| * @description Label for an event in the Performance panel indicating that a |
| * callback function has been scheduled to run at a later time using the |
| * postTask API. |
| */ |
| schedulePostTaskCallback: 'Schedule postTask', |
| /** |
| * @description Label for an event in the Performance panel indicating that a |
| * callback function that was scheduled to run using the postTask API was |
| * fired (invoked). |
| */ |
| runPostTaskCallback: 'Fire postTask', |
| /** |
| * @description Label for an event in the Performance panel indicating that a |
| * callback function that was scheduled to run at a later time using the |
| * postTask API was cancelled, so will no longer run. |
| */ |
| abortPostTaskCallback: 'Cancel postTask', |
| } as const; |
| |
| export enum EventCategory { |
| DRAWING = 'drawing', |
| RASTERIZING = 'rasterizing', |
| LAYOUT = 'layout', |
| LOADING = 'loading', |
| EXPERIENCE = 'experience', |
| SCRIPTING = 'scripting', |
| MESSAGING = 'messaging', |
| RENDERING = 'rendering', |
| PAINTING = 'painting', |
| GPU = 'gpu', |
| ASYNC = 'async', |
| OTHER = 'other', |
| IDLE = 'idle', |
| } |
| |
| let mainEventCategories: EventCategory[]; |
| |
| const str_ = i18n.i18n.registerUIStrings('models/trace/Styles.ts', UIStrings); |
| const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); |
| |
| export class TimelineRecordStyle { |
| title: string; |
| category: TimelineCategory; |
| hidden: boolean; |
| |
| constructor(title: string, category: TimelineCategory, hidden: boolean|undefined = false) { |
| this.title = title; |
| this.category = category; |
| this.hidden = hidden; |
| } |
| } |
| export class TimelineCategory { |
| name: EventCategory; |
| title: Platform.UIString.LocalizedString; |
| visible: boolean; |
| #hidden?: boolean; |
| #cssVariable: `--app-color-${string}`; |
| |
| constructor( |
| name: EventCategory, title: Platform.UIString.LocalizedString, visible: boolean, |
| cssVariable: `--app-color-${string}`) { |
| this.name = name; |
| this.title = title; |
| this.visible = visible; |
| this.#cssVariable = cssVariable; |
| this.hidden = false; |
| } |
| |
| get hidden(): boolean { |
| return Boolean(this.#hidden); |
| } |
| |
| get cssVariable(): string { |
| return this.#cssVariable; |
| } |
| |
| getCSSValue(): string { |
| return `var(${this.#cssVariable})`; |
| } |
| |
| set hidden(hidden: boolean) { |
| this.#hidden = hidden; |
| } |
| } |
| |
| export type CategoryPalette = Record<EventCategory, TimelineCategory>; |
| |
| type EventStylesMap = Partial<Record<Types.Events.Name, TimelineRecordStyle>>; |
| |
| /** |
| * This object defines the styles for the categories used in the |
| * timeline (loading, rendering, scripting, etc.). |
| */ |
| let categoryStyles: CategoryPalette|null; |
| |
| /** |
| * This map defines the styles for events shown in the panel. This |
| * includes its color (which on the event's category, the label it's |
| * displayed with and flag to know weather it's visible in the flamechart |
| * or not). |
| * The thread appenders use this map to determine if an event should be |
| * shown in the flame chart. If an event is not in the map, then it |
| * won't be shown, but it also won't be shown if it's marked as "hidden" |
| * in its styles. |
| * |
| * The map is also used in other places, like the event's details view. |
| */ |
| let eventStylesMap: EventStylesMap|null; |
| |
| export function getEventStyle(eventName: Types.Events.Name): TimelineRecordStyle|undefined { |
| return maybeInitSylesMap()[eventName]; |
| } |
| |
| export function stringIsEventCategory(it: string): it is EventCategory { |
| return (Object.values(EventCategory) as string[]).includes(it); |
| } |
| |
| export function getCategoryStyles(): CategoryPalette { |
| if (categoryStyles) { |
| return categoryStyles; |
| } |
| categoryStyles = { |
| loading: new TimelineCategory(EventCategory.LOADING, i18nString(UIStrings.loading), true, '--app-color-loading'), |
| experience: new TimelineCategory( |
| EventCategory.EXPERIENCE, i18nString(UIStrings.experience), false, '--app-color-rendering'), |
| messaging: |
| new TimelineCategory(EventCategory.MESSAGING, i18nString(UIStrings.messaging), true, '--app-color-messaging'), |
| scripting: |
| new TimelineCategory(EventCategory.SCRIPTING, i18nString(UIStrings.scripting), true, '--app-color-scripting'), |
| rendering: |
| new TimelineCategory(EventCategory.RENDERING, i18nString(UIStrings.rendering), true, '--app-color-rendering'), |
| painting: |
| new TimelineCategory(EventCategory.PAINTING, i18nString(UIStrings.painting), true, '--app-color-painting'), |
| gpu: new TimelineCategory(EventCategory.GPU, i18nString(UIStrings.gpu), false, '--app-color-painting'), |
| async: new TimelineCategory(EventCategory.ASYNC, i18nString(UIStrings.async), false, '--app-color-async'), |
| other: new TimelineCategory(EventCategory.OTHER, i18nString(UIStrings.system), false, '--app-color-system'), |
| idle: new TimelineCategory(EventCategory.IDLE, i18nString(UIStrings.idle), false, '--app-color-idle'), |
| layout: new TimelineCategory(EventCategory.LAYOUT, i18nString(UIStrings.layout), false, '--app-color-loading'), |
| rasterizing: new TimelineCategory( |
| EventCategory.RASTERIZING, i18nString(UIStrings.rasterizing), false, '--app-color-scripting'), |
| drawing: new TimelineCategory(EventCategory.DRAWING, i18nString(UIStrings.drawing), false, '--app-color-rendering'), |
| }; |
| return categoryStyles; |
| } |
| |
| export function maybeInitSylesMap(): EventStylesMap { |
| if (eventStylesMap) { |
| return eventStylesMap; |
| } |
| const defaultCategoryStyles = getCategoryStyles(); |
| |
| eventStylesMap = { |
| [Types.Events.Name.RUN_TASK]: new TimelineRecordStyle(i18nString(UIStrings.task), defaultCategoryStyles.other), |
| |
| [Types.Events.Name.PROFILE_CALL]: |
| new TimelineRecordStyle(i18nString(UIStrings.jsFrame), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.JS_SAMPLE]: |
| new TimelineRecordStyle(Types.Events.Name.JS_SAMPLE, defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.PROGRAM]: new TimelineRecordStyle(i18nString(UIStrings.other), defaultCategoryStyles.other), |
| |
| [Types.Events.Name.START_PROFILING]: |
| new TimelineRecordStyle(i18nString(UIStrings.profilingOverhead), defaultCategoryStyles.other), |
| |
| [Types.Events.Name.ANIMATION]: |
| new TimelineRecordStyle(i18nString(UIStrings.animation), defaultCategoryStyles.rendering), |
| |
| [Types.Events.Name.EVENT_DISPATCH]: |
| new TimelineRecordStyle(i18nString(UIStrings.event), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.REQUEST_MAIN_THREAD_FRAME]: new TimelineRecordStyle( |
| i18nString(UIStrings.requestMainThreadFrame), |
| defaultCategoryStyles.rendering, |
| true, |
| ), |
| |
| [Types.Events.Name.BEGIN_FRAME]: new TimelineRecordStyle( |
| i18nString(UIStrings.frameStart), |
| defaultCategoryStyles.rendering, |
| true, |
| ), |
| |
| [Types.Events.Name.BEGIN_MAIN_THREAD_FRAME]: new TimelineRecordStyle( |
| i18nString(UIStrings.frameStartMainThread), |
| defaultCategoryStyles.rendering, |
| true, |
| ), |
| |
| [Types.Events.Name.DRAW_FRAME]: new TimelineRecordStyle( |
| i18nString(UIStrings.drawFrame), |
| defaultCategoryStyles.rendering, |
| true, |
| ), |
| |
| [Types.Events.Name.HIT_TEST]: |
| new TimelineRecordStyle(i18nString(UIStrings.hitTest), defaultCategoryStyles.rendering), |
| |
| [Types.Events.Name.SCHEDULE_STYLE_RECALCULATION]: new TimelineRecordStyle( |
| i18nString(UIStrings.scheduleStyleRecalculation), |
| defaultCategoryStyles.rendering, |
| ), |
| |
| [Types.Events.Name.RECALC_STYLE]: |
| new TimelineRecordStyle(i18nString(UIStrings.recalculateStyle), defaultCategoryStyles.rendering), |
| |
| [Types.Events.Name.INVALIDATE_LAYOUT]: new TimelineRecordStyle( |
| i18nString(UIStrings.invalidateLayout), |
| defaultCategoryStyles.rendering, |
| true, |
| ), |
| |
| [Types.Events.Name.LAYERIZE]: |
| new TimelineRecordStyle(i18nString(UIStrings.layerize), defaultCategoryStyles.rendering), |
| |
| [Types.Events.Name.LAYOUT]: new TimelineRecordStyle(i18nString(UIStrings.layout), defaultCategoryStyles.rendering), |
| |
| [Types.Events.Name.PAINT_SETUP]: |
| new TimelineRecordStyle(i18nString(UIStrings.paintSetup), defaultCategoryStyles.painting), |
| |
| [Types.Events.Name.PAINT_IMAGE]: new TimelineRecordStyle( |
| i18nString(UIStrings.paintImage), |
| defaultCategoryStyles.painting, |
| true, |
| ), |
| |
| [Types.Events.Name.UPDATE_LAYER]: new TimelineRecordStyle( |
| i18nString(UIStrings.updateLayer), |
| defaultCategoryStyles.painting, |
| true, |
| ), |
| |
| [Types.Events.Name.UPDATE_LAYER_TREE]: |
| new TimelineRecordStyle(i18nString(UIStrings.updateLayerTree), defaultCategoryStyles.rendering), |
| |
| [Types.Events.Name.PAINT]: new TimelineRecordStyle(i18nString(UIStrings.paint), defaultCategoryStyles.painting), |
| |
| [Types.Events.Name.PRE_PAINT]: |
| new TimelineRecordStyle(i18nString(UIStrings.prePaint), defaultCategoryStyles.rendering), |
| |
| [Types.Events.Name.RASTER_TASK]: |
| new TimelineRecordStyle(i18nString(UIStrings.rasterizePaint), defaultCategoryStyles.painting), |
| |
| [Types.Events.Name.SCROLL_LAYER]: |
| new TimelineRecordStyle(i18nString(UIStrings.scroll), defaultCategoryStyles.rendering), |
| |
| [Types.Events.Name.COMMIT]: new TimelineRecordStyle(i18nString(UIStrings.commit), defaultCategoryStyles.painting), |
| |
| [Types.Events.Name.COMPOSITE_LAYERS]: |
| new TimelineRecordStyle(i18nString(UIStrings.compositeLayers), defaultCategoryStyles.painting), |
| |
| [Types.Events.Name.COMPUTE_INTERSECTION]: new TimelineRecordStyle( |
| i18nString(UIStrings.computeIntersections), |
| defaultCategoryStyles.rendering, |
| ), |
| |
| [Types.Events.Name.PARSE_HTML]: |
| new TimelineRecordStyle(i18nString(UIStrings.parseHtml), defaultCategoryStyles.loading), |
| |
| [Types.Events.Name.PARSE_AUTHOR_STYLE_SHEET]: |
| new TimelineRecordStyle(i18nString(UIStrings.parseStylesheet), defaultCategoryStyles.loading), |
| |
| [Types.Events.Name.TIMER_INSTALL]: |
| new TimelineRecordStyle(i18nString(UIStrings.installTimer), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.TIMER_REMOVE]: |
| new TimelineRecordStyle(i18nString(UIStrings.removeTimer), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.TIMER_FIRE]: |
| new TimelineRecordStyle(i18nString(UIStrings.timerFired), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.XHR_READY_STATE_CHANGED]: new TimelineRecordStyle( |
| i18nString(UIStrings.xhrReadyStateChange), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.XHR_LOAD]: |
| new TimelineRecordStyle(i18nString(UIStrings.xhrLoad), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.COMPILE]: |
| new TimelineRecordStyle(i18nString(UIStrings.compileScript), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CACHE_SCRIPT]: |
| new TimelineRecordStyle(i18nString(UIStrings.cacheScript), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.COMPILE_CODE]: |
| new TimelineRecordStyle(i18nString(UIStrings.compileCode), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.OPTIMIZE_CODE]: |
| new TimelineRecordStyle(i18nString(UIStrings.optimizeCode), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.EVALUATE_SCRIPT]: |
| new TimelineRecordStyle(i18nString(UIStrings.evaluateScript), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.COMPILE_MODULE]: |
| new TimelineRecordStyle(i18nString(UIStrings.compileModule), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CACHE_MODULE]: |
| new TimelineRecordStyle(i18nString(UIStrings.cacheModule), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.EVALUATE_MODULE]: |
| new TimelineRecordStyle(i18nString(UIStrings.evaluateModule), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.STREAMING_COMPILE_SCRIPT]: |
| new TimelineRecordStyle(i18nString(UIStrings.streamingCompileTask), defaultCategoryStyles.other), |
| |
| [Types.Events.Name.STREAMING_COMPILE_SCRIPT_WAITING]: |
| new TimelineRecordStyle(i18nString(UIStrings.waitingForNetwork), defaultCategoryStyles.idle), |
| |
| [Types.Events.Name.STREAMING_COMPILE_SCRIPT_PARSING]: |
| new TimelineRecordStyle(i18nString(UIStrings.parseAndCompile), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.BACKGROUND_DESERIALIZE]: new TimelineRecordStyle( |
| i18nString(UIStrings.deserializeCodeCache), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.FINALIZE_DESERIALIZATION]: |
| new TimelineRecordStyle(i18nString(UIStrings.profilingOverhead), defaultCategoryStyles.other), |
| |
| [Types.Events.Name.WASM_STREAM_FROM_RESPONSE_CALLBACK]: new TimelineRecordStyle( |
| i18nString(UIStrings.streamingWasmResponse), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.WASM_COMPILED_MODULE]: |
| new TimelineRecordStyle(i18nString(UIStrings.compiledWasmModule), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.WASM_CACHED_MODULE]: |
| new TimelineRecordStyle(i18nString(UIStrings.cachedWasmModule), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.WASM_MODULE_CACHE_HIT]: |
| new TimelineRecordStyle(i18nString(UIStrings.wasmModuleCacheHit), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.WASM_MODULE_CACHE_INVALID]: new TimelineRecordStyle( |
| i18nString(UIStrings.wasmModuleCacheInvalid), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.FRAME_STARTED_LOADING]: new TimelineRecordStyle( |
| i18nString(UIStrings.frameStartedLoading), |
| defaultCategoryStyles.loading, |
| true, |
| ), |
| |
| [Types.Events.Name.MARK_LOAD]: new TimelineRecordStyle( |
| i18nString(UIStrings.onloadEvent), |
| defaultCategoryStyles.scripting, |
| true, |
| ), |
| |
| [Types.Events.Name.MARK_DOM_CONTENT]: new TimelineRecordStyle( |
| i18nString(UIStrings.domcontentloadedEvent), |
| defaultCategoryStyles.scripting, |
| true, |
| ), |
| |
| [Types.Events.Name.MARK_FIRST_PAINT]: new TimelineRecordStyle( |
| i18nString(UIStrings.firstPaint), |
| defaultCategoryStyles.painting, |
| true, |
| ), |
| |
| [Types.Events.Name.MARK_FCP]: new TimelineRecordStyle( |
| i18nString(UIStrings.firstContentfulPaint), |
| defaultCategoryStyles.rendering, |
| true, |
| ), |
| |
| [Types.Events.Name.MARK_LCP_CANDIDATE]: new TimelineRecordStyle( |
| i18nString(UIStrings.largestContentfulPaint), |
| defaultCategoryStyles.rendering, |
| true, |
| ), |
| [Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: new TimelineRecordStyle( |
| i18nString(UIStrings.softLargestContentfulPaint), |
| defaultCategoryStyles.rendering, |
| true, |
| ), |
| |
| [Types.Events.Name.TIME_STAMP]: |
| new TimelineRecordStyle(i18nString(UIStrings.timestamp), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CONSOLE_TIME]: |
| new TimelineRecordStyle(i18nString(UIStrings.consoleTime), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.USER_TIMING]: |
| new TimelineRecordStyle(i18nString(UIStrings.userTiming), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.RESOURCE_WILL_SEND_REQUEST]: |
| new TimelineRecordStyle(i18nString(UIStrings.willSendRequest), defaultCategoryStyles.loading), |
| |
| [Types.Events.Name.RESOURCE_SEND_REQUEST]: |
| new TimelineRecordStyle(i18nString(UIStrings.sendRequest), defaultCategoryStyles.loading), |
| |
| [Types.Events.Name.RESOURCE_RECEIVE_RESPONSE]: |
| new TimelineRecordStyle(i18nString(UIStrings.receiveResponse), defaultCategoryStyles.loading), |
| |
| [Types.Events.Name.RESOURCE_FINISH]: |
| new TimelineRecordStyle(i18nString(UIStrings.finishLoading), defaultCategoryStyles.loading), |
| |
| [Types.Events.Name.RESOURCE_RECEIVE_DATA]: |
| new TimelineRecordStyle(i18nString(UIStrings.receiveData), defaultCategoryStyles.loading), |
| |
| [Types.Events.Name.RUN_MICROTASKS]: |
| new TimelineRecordStyle(i18nString(UIStrings.runMicrotasks), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.FUNCTION_CALL]: |
| new TimelineRecordStyle(i18nString(UIStrings.functionCall), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.GC]: new TimelineRecordStyle(i18nString(UIStrings.gcEvent), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.MAJOR_GC]: |
| new TimelineRecordStyle(i18nString(UIStrings.majorGc), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.MINOR_GC]: |
| new TimelineRecordStyle(i18nString(UIStrings.minorGc), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CPPGC_SWEEP]: |
| new TimelineRecordStyle(i18nString(UIStrings.cppGc), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.REQUEST_ANIMATION_FRAME]: new TimelineRecordStyle( |
| i18nString(UIStrings.requestAnimationFrame), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.CANCEL_ANIMATION_FRAME]: new TimelineRecordStyle( |
| i18nString(UIStrings.cancelAnimationFrame), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.FIRE_ANIMATION_FRAME]: new TimelineRecordStyle( |
| i18nString(UIStrings.animationFrameFired), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.REQUEST_IDLE_CALLBACK]: new TimelineRecordStyle( |
| i18nString(UIStrings.requestIdleCallback), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.CANCEL_IDLE_CALLBACK]: |
| new TimelineRecordStyle(i18nString(UIStrings.cancelIdleCallback), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.FIRE_IDLE_CALLBACK]: |
| new TimelineRecordStyle(i18nString(UIStrings.fireIdleCallback), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.WEB_SOCKET_CREATE]: |
| new TimelineRecordStyle(i18nString(UIStrings.createWebsocket), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST]: new TimelineRecordStyle( |
| i18nString(UIStrings.sendWebsocketHandshake), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST]: new TimelineRecordStyle( |
| i18nString(UIStrings.receiveWebsocketHandshake), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.WEB_SOCKET_DESTROY]: |
| new TimelineRecordStyle(i18nString(UIStrings.destroyWebsocket), defaultCategoryStyles.scripting), |
| [Types.Events.Name.WEB_SOCKET_SEND]: new TimelineRecordStyle( |
| i18nString(UIStrings.wsMessageSent), |
| defaultCategoryStyles.scripting, |
| ), |
| [Types.Events.Name.WEB_SOCKET_RECEIVE]: new TimelineRecordStyle( |
| i18nString(UIStrings.wsMessageReceived), |
| defaultCategoryStyles.scripting, |
| ), |
| |
| [Types.Events.Name.EMBEDDER_CALLBACK]: |
| new TimelineRecordStyle(i18nString(UIStrings.embedderCallback), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.DECODE_IMAGE]: |
| new TimelineRecordStyle(i18nString(UIStrings.imageDecode), defaultCategoryStyles.painting), |
| |
| [Types.Events.Name.GPU_TASK]: new TimelineRecordStyle(i18nString(UIStrings.gpu), defaultCategoryStyles.gpu), |
| |
| [Types.Events.Name.GC_COLLECT_GARBARGE]: |
| new TimelineRecordStyle(i18nString(UIStrings.domGc), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_ENCRYPT]: |
| new TimelineRecordStyle(i18nString(UIStrings.encrypt), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_ENCRYPT_REPLY]: |
| new TimelineRecordStyle(i18nString(UIStrings.encryptReply), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_DECRYPT]: |
| new TimelineRecordStyle(i18nString(UIStrings.decrypt), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_DECRYPT_REPLY]: |
| new TimelineRecordStyle(i18nString(UIStrings.decryptReply), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_DIGEST]: |
| new TimelineRecordStyle(i18nString(UIStrings.digest), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_DIGEST_REPLY]: |
| new TimelineRecordStyle(i18nString(UIStrings.digestReply), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_SIGN]: |
| new TimelineRecordStyle(i18nString(UIStrings.sign), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_SIGN_REPLY]: |
| new TimelineRecordStyle(i18nString(UIStrings.signReply), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_VERIFY]: |
| new TimelineRecordStyle(i18nString(UIStrings.verify), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.CRYPTO_DO_VERIFY_REPLY]: |
| new TimelineRecordStyle(i18nString(UIStrings.verifyReply), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.ASYNC_TASK]: |
| new TimelineRecordStyle(i18nString(UIStrings.asyncTask), defaultCategoryStyles.async), |
| |
| [Types.Events.Name.LAYOUT_SHIFT]: new TimelineRecordStyle( |
| i18nString(UIStrings.layoutShift), defaultCategoryStyles.experience, |
| /* Mark LayoutShifts as hidden; in the timeline we render |
| * SyntheticLayoutShifts so those are the ones visible to the user */ |
| true), |
| |
| [Types.Events.Name.SYNTHETIC_LAYOUT_SHIFT]: |
| new TimelineRecordStyle(i18nString(UIStrings.layoutShift), defaultCategoryStyles.experience), |
| |
| [Types.Events.Name.SYNTHETIC_LAYOUT_SHIFT_CLUSTER]: |
| new TimelineRecordStyle(i18nString(UIStrings.layoutShiftCluster), defaultCategoryStyles.experience), |
| |
| [Types.Events.Name.EVENT_TIMING]: |
| new TimelineRecordStyle(i18nString(UIStrings.eventTiming), defaultCategoryStyles.experience), |
| |
| [Types.Events.Name.HANDLE_POST_MESSAGE]: |
| new TimelineRecordStyle(i18nString(UIStrings.onMessage), defaultCategoryStyles.messaging), |
| |
| [Types.Events.Name.SCHEDULE_POST_MESSAGE]: |
| new TimelineRecordStyle(i18nString(UIStrings.schedulePostMessage), defaultCategoryStyles.messaging), |
| |
| [Types.Events.Name.SCHEDULE_POST_TASK_CALLBACK]: |
| new TimelineRecordStyle(i18nString(UIStrings.schedulePostTaskCallback), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.RUN_POST_TASK_CALLBACK]: |
| new TimelineRecordStyle(i18nString(UIStrings.runPostTaskCallback), defaultCategoryStyles.scripting), |
| |
| [Types.Events.Name.ABORT_POST_TASK_CALLBACK]: |
| new TimelineRecordStyle(i18nString(UIStrings.abortPostTaskCallback), defaultCategoryStyles.scripting), |
| [Types.Events.Name.V8_CONSOLE_RUN_TASK]: |
| new TimelineRecordStyle(i18nString(UIStrings.consoleTaskRun), defaultCategoryStyles.scripting), |
| }; |
| |
| // TODO(crbug.com/410884528): remove assertion after deduped eventStylesMap for VISIBLE_TRACE_EVENT_TYPES. |
| const visibleEventStyles = |
| Object.entries(eventStylesMap).filter(([, style]) => style.hidden === false).map(([ |
| key, |
| ]) => key); |
| const visibleTraceEventsComplete = visibleEventStyles.every(eventType => { |
| return Helpers.Trace.VISIBLE_TRACE_EVENT_TYPES.has(eventType as Types.Events.Name); |
| }); |
| |
| const eventStylesMapKeys = Object.keys(eventStylesMap) as Types.Events.Name[]; |
| const eventStylesComplete = Array.from(Helpers.Trace.VISIBLE_TRACE_EVENT_TYPES).every(eventType => { |
| return eventStylesMapKeys.includes(eventType); |
| }); |
| |
| if (!visibleTraceEventsComplete || !eventStylesComplete) { |
| throw new Error('eventStylesMap and VISIBLE_TRACE_EVENT_TYPES are out of sync!'); |
| } |
| return eventStylesMap; |
| } |
| |
| export function setEventStylesMap(eventStyles: EventStylesMap): void { |
| eventStylesMap = eventStyles; |
| } |
| |
| export function setCategories(cats: CategoryPalette): void { |
| categoryStyles = cats; |
| } |
| |
| export function visibleTypes(): string[] { |
| const eventStyles = maybeInitSylesMap(); |
| const result = []; |
| for (const name in eventStyles) { |
| // Typescript cannot infer that `name` is a key of eventStyles |
| const nameAsKey = name as keyof typeof eventStyles; |
| if (!eventStyles[nameAsKey]?.hidden) { |
| result.push(name); |
| } |
| } |
| return result; |
| } |
| |
| export function getTimelineMainEventCategories(): EventCategory[] { |
| if (mainEventCategories) { |
| return mainEventCategories; |
| } |
| mainEventCategories = [ |
| EventCategory.IDLE, |
| EventCategory.LOADING, |
| EventCategory.PAINTING, |
| EventCategory.RENDERING, |
| EventCategory.SCRIPTING, |
| EventCategory.OTHER, |
| ]; |
| return mainEventCategories; |
| } |
| |
| export function setTimelineMainEventCategories(categories: EventCategory[]): void { |
| mainEventCategories = categories; |
| } |
| |
| export function markerDetailsForEvent(event: Types.Events.Event): { |
| color: string, |
| title: string, |
| } { |
| let title = ''; |
| let color = 'var(--color-text-primary)'; |
| if (Types.Events.isFirstContentfulPaint(event)) { |
| color = 'var(--sys-color-green-bright)'; |
| title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP; |
| } |
| if (Types.Events.isAnyLargestContentfulPaintCandidate(event)) { |
| color = 'var(--sys-color-green)'; |
| title = Types.Events.isSoftLargestContentfulPaintCandidate(event) ? |
| Handlers.ModelHandlers.PageLoadMetrics.MetricName.SOFT_LCP : |
| Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP; |
| } |
| if (Types.Events.isNavigationStart(event) || Types.Events.isSoftNavigationStart(event)) { |
| color = 'var(--color-text-primary)'; |
| title = Types.Events.isSoftNavigationStart(event) ? Handlers.ModelHandlers.PageLoadMetrics.MetricName.SOFT_NAV : |
| Handlers.ModelHandlers.PageLoadMetrics.MetricName.NAV; |
| } |
| if (Types.Events.isMarkDOMContent(event)) { |
| color = 'var(--color-text-disabled)'; |
| title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL; |
| } |
| if (Types.Events.isMarkLoad(event)) { |
| color = 'var(--color-text-disabled)'; |
| title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.L; |
| } |
| return {color, title}; |
| } |