| // 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 Trace from '../../../models/trace/trace.js'; |
| |
| const imageCache = |
| new WeakMap<Trace.Types.Events.LegacySyntheticScreenshot|Trace.Types.Events.Screenshot, HTMLImageElement|null>(); |
| export const emitter = new EventTarget(); |
| |
| /** |
| * Synchronously returns an image, or return `null` while queuing up an async load of that image. |
| * If the image load fails, we cache a null to avoid reattempts. |
| */ |
| export function getOrQueue(screenshot: Trace.Types.Events.LegacySyntheticScreenshot| |
| Trace.Types.Events.Screenshot): HTMLImageElement|null { |
| if (imageCache.has(screenshot)) { |
| return imageCache.get(screenshot) ?? null; |
| } |
| |
| const uri = Trace.Handlers.ModelHandlers.Screenshots.screenshotImageDataUri(screenshot); |
| |
| loadImage(uri) |
| .then(imageOrNull => { |
| imageCache.set(screenshot, imageOrNull); |
| emitter.dispatchEvent(new CustomEvent('screenshot-loaded', {detail: {screenshot, image: imageOrNull}})); |
| }) |
| .catch(() => {}); |
| return null; |
| } |
| |
| /** Load an image (probably data URI). If it fails, resolve with null. */ |
| function loadImage(url: string): Promise<HTMLImageElement|null> { |
| return new Promise(resolve => { |
| const image = new Image(); |
| image.addEventListener('load', () => resolve(image)); |
| image.addEventListener('error', () => resolve(null)); |
| image.src = url; |
| }); |
| } |
| |
| /** Populate the cache ahead of use, to allow for getOrQueue to synchronously return images. */ |
| export function preload(screenshots: Array<Trace.Types.Events.LegacySyntheticScreenshot|Trace.Types.Events.Screenshot>): |
| Promise<void[]> { |
| const promises = screenshots.map(screenshot => { |
| if (imageCache.has(screenshot)) { |
| return; |
| } |
| const uri = Trace.Handlers.ModelHandlers.Screenshots.screenshotImageDataUri(screenshot); |
| return loadImage(uri).then(image => { |
| imageCache.set(screenshot, image); |
| return; |
| }); |
| }); |
| return Promise.all(promises); |
| } |
| |
| export const cacheForTesting = imageCache; |
| export const loadImageForTesting = loadImage; |