{"version":3,"file":"AuctionWorkletsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/AuctionWorkletsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 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\n/**\n * There are two metadata events that we care about.\n * => AuctionWorkletRunningInProcess tells us which process the Auction Worklet\n * has taken to run in.\n * => AuctionWorkletDoneWithProcess tells us when the worklet is done with that\n * process. This is less useful - but in the future we might want to surface\n * this information so we still parse and return the event.\n *\n * It is important to note that the top level PID on these events is NOT the\n * PID that the worklet is running on; instead we have to look at its\n * args.data.pid property, which is the PID of the process that it is running\n * on.\n *\n * For any given RunningInProcess event, we would typically expect to see a\n * DoneWithProcess event, however this is not guaranteed, especially as users\n * can record any chunk of time in DevTools.\n *\n * Similarly, it is also possible to see a DoneWithProcess event without a\n * RunningInProcess event, if the user started recording after the auction\n * worklets started. Therefore we are happy to create\n * SyntheticAuctionWorklets as long as we see just one of these events.\n *\n * If we do get two events and need to pair them, we can use the\n * args.data.target property, which is a string ID shared by both\n * events.\n */\nconst runningInProcessEvents = new Map();\nconst doneWithProcessEvents = new Map();\n\n// Keyed by the PID defined in `args.data.pid` on AuctionWorklet trace events..\nconst createdSyntheticEvents = new Map();\n\n// Each AuctonWorklet takes over a process and has 2 threads (that we care\n// about and want to show as tracks):\n// 1. A CrUtilityMain thread which is known as the \"control process\".\n// 2. A AuctionV8HelperThread which is the actual auction worklet and will be\n// either a \"Seller\" or a \"Bidder\"\n// To detect these we look for the metadata thread_name events. We key these by\n// PID so that we can easily look them up later without having to loop through.\nconst utilityThreads = new Map();\nconst v8HelperThreads = new Map();\n\nexport function reset(): void {\n runningInProcessEvents.clear();\n doneWithProcessEvents.clear();\n createdSyntheticEvents.clear();\n utilityThreads.clear();\n v8HelperThreads.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isAuctionWorkletRunningInProcess(event)) {\n runningInProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.Events.isAuctionWorkletDoneWithProcess(event)) {\n doneWithProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.Events.isThreadName(event)) {\n if (event.args.name === 'auction_worklet.CrUtilityMain') {\n utilityThreads.set(event.pid, event);\n return;\n }\n if (event.args.name === 'AuctionV8HelperThread') {\n v8HelperThreads.set(event.pid, event);\n }\n }\n}\n\nfunction workletType(input: string): Types.Events.AuctionWorkletType {\n switch (input) {\n case 'seller':\n return Types.Events.AuctionWorkletType.SELLER;\n case 'bidder':\n return Types.Events.AuctionWorkletType.BIDDER;\n default:\n return Types.Events.AuctionWorkletType.UNKNOWN;\n }\n}\n\n/**\n * We cannot make the full event without knowing the type of event, but we can\n * create everything other than the `args` field, as those are identical\n * regardless of the type of event.\n */\nfunction makeSyntheticEventBase(event: Types.Events.AuctionWorkletDoneWithProcess|\n Types.Events.AuctionWorkletRunningInProcess):\n Omit {\n return Helpers.SyntheticEvents.SyntheticEventsManager\n .registerSyntheticEvent>({\n rawSourceEvent: event,\n name: 'SyntheticAuctionWorklet',\n s: Types.Events.Scope.THREAD,\n cat: event.cat,\n tid: event.tid,\n ts: event.ts,\n ph: Types.Events.Phase.INSTANT,\n pid: event.args.data.pid,\n host: event.args.data.host,\n target: event.args.data.target,\n type: workletType(event.args.data.type),\n });\n}\n\nexport async function finalize(): Promise {\n // Loop through the utility threads we found to create the worklet events. We\n // expect each worklet to have a utility thread, so we can use them as the\n // root of our list of worklets.\n for (const [pid, utilityThreadNameEvent] of utilityThreads) {\n const v8HelperEvent = v8HelperThreads.get(pid);\n if (!v8HelperEvent) {\n // Bad trace data - AuctionWorklets are expected to always have both threads.\n continue;\n }\n\n const runningEvent = runningInProcessEvents.get(pid);\n const doneWithEvent = doneWithProcessEvents.get(pid);\n\n // We can create a worklet from either the runningEvent or doneWithEvent -\n // we do not need both. We cannot express that to TypeScript with an early\n // return here, so instead we set the event initially to null, and then\n // create it from either the running event or the doneWith event. If it is\n // still null after this, that means neither event was found, and we drop\n // the worklet as we do not have enough information to create the synthetic\n // event.\n\n let syntheticEvent: Types.Events.SyntheticAuctionWorklet|null = null;\n\n if (runningEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(runningEvent),\n args: {\n data: {\n runningInProcessEvent: runningEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (doneWithEvent) {\n syntheticEvent.args.data.doneWithProcessEvent = doneWithEvent;\n }\n } else if (doneWithEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(doneWithEvent),\n args: {\n data: {\n doneWithProcessEvent: doneWithEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (runningEvent) {\n syntheticEvent.args.data.runningInProcessEvent = runningEvent;\n }\n }\n if (syntheticEvent === null) {\n continue;\n }\n createdSyntheticEvents.set(pid, syntheticEvent);\n }\n}\n\nexport interface AuctionWorkletsData {\n worklets: Map;\n}\n\nexport function data(): AuctionWorkletsData {\n return {\n worklets: new Map(createdSyntheticEvents),\n };\n}\n"]}