UNPKG

chrome-devtools-frontend

Version:
205 lines (165 loc) • 7.79 kB
// 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 type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js'; import type * as Protocol from '../../generated/protocol.js'; import type * as Common from '../common/common.js'; import {SDKModel} from './SDKModel.js'; import {Events as StorageKeyManagerEvents, StorageKeyManager} from './StorageKeyManager.js'; import {Capability, type Target} from './Target.js'; export class StorageBucketsModel extends SDKModel<EventTypes> implements ProtocolProxyApi.StorageDispatcher { private enabled = false; readonly storageAgent: ProtocolProxyApi.StorageApi; private readonly storageKeyManager: StorageKeyManager|null; private bucketsById = new Map<string, Protocol.Storage.StorageBucketInfo>(); private trackedStorageKeys = new Set<string>(); constructor(target: Target) { super(target); target.registerStorageDispatcher(this); this.storageAgent = target.storageAgent(); this.storageKeyManager = target.model(StorageKeyManager); } getBuckets(): Set<Protocol.Storage.StorageBucketInfo> { return new Set(this.bucketsById.values()); } getBucketsForStorageKey(storageKey: string): Set<Protocol.Storage.StorageBucketInfo> { const buckets = [...this.bucketsById.values()]; return new Set(buckets.filter(({bucket}) => bucket.storageKey === storageKey)); } getDefaultBucketForStorageKey(storageKey: string): Protocol.Storage.StorageBucketInfo|null { const buckets = [...this.bucketsById.values()]; return buckets.find(({bucket}) => bucket.storageKey === storageKey && bucket.name === undefined) ?? null; } getBucketById(bucketId: string): Protocol.Storage.StorageBucketInfo|null { return this.bucketsById.get(bucketId) ?? null; } getBucketByName(storageKey: string, bucketName?: string): Protocol.Storage.StorageBucketInfo|null { if (!bucketName) { return this.getDefaultBucketForStorageKey(storageKey); } const buckets = [...this.bucketsById.values()]; return buckets.find(({bucket}) => bucket.storageKey === storageKey && bucket.name === bucketName) ?? null; } deleteBucket(bucket: Protocol.Storage.StorageBucket): void { void this.storageAgent.invoke_deleteStorageBucket({bucket}); } enable(): void { if (this.enabled) { return; } if (this.storageKeyManager) { this.storageKeyManager.addEventListener(StorageKeyManagerEvents.STORAGE_KEY_ADDED, this.storageKeyAdded, this); this.storageKeyManager.addEventListener( StorageKeyManagerEvents.STORAGE_KEY_REMOVED, this.storageKeyRemoved, this); for (const storageKey of this.storageKeyManager.storageKeys()) { this.addStorageKey(storageKey); } } this.enabled = true; } private storageKeyAdded(event: Common.EventTarget.EventTargetEvent<string>): void { this.addStorageKey(event.data); } private storageKeyRemoved(event: Common.EventTarget.EventTargetEvent<string>): void { this.removeStorageKey(event.data); } private addStorageKey(storageKey: string): void { if (this.trackedStorageKeys.has(storageKey)) { throw new Error('Can\'t call addStorageKey for a storage key if it has already been added.'); } this.trackedStorageKeys.add(storageKey); void this.storageAgent.invoke_setStorageBucketTracking({storageKey, enable: true}); } private removeStorageKey(storageKey: string): void { if (!this.trackedStorageKeys.has(storageKey)) { throw new Error('Can\'t call removeStorageKey for a storage key if it hasn\'t already been added.'); } const bucketsForStorageKey = this.getBucketsForStorageKey(storageKey); for (const bucket of bucketsForStorageKey) { this.bucketRemoved(bucket); } this.trackedStorageKeys.delete(storageKey); void this.storageAgent.invoke_setStorageBucketTracking({storageKey, enable: false}); } private bucketAdded(bucketInfo: Protocol.Storage.StorageBucketInfo): void { this.bucketsById.set(bucketInfo.id, bucketInfo); this.dispatchEventToListeners(Events.BUCKET_ADDED, {model: this, bucketInfo}); } private bucketRemoved(bucketInfo: Protocol.Storage.StorageBucketInfo): void { this.bucketsById.delete(bucketInfo.id); this.dispatchEventToListeners(Events.BUCKET_REMOVED, {model: this, bucketInfo}); } private bucketChanged(bucketInfo: Protocol.Storage.StorageBucketInfo): void { this.dispatchEventToListeners(Events.BUCKET_CHANGED, {model: this, bucketInfo}); } private bucketInfosAreEqual( bucketInfo1: Protocol.Storage.StorageBucketInfo, bucketInfo2: Protocol.Storage.StorageBucketInfo): boolean { return bucketInfo1.bucket.storageKey === bucketInfo2.bucket.storageKey && bucketInfo1.id === bucketInfo2.id && bucketInfo1.bucket.name === bucketInfo2.bucket.name && bucketInfo1.expiration === bucketInfo2.expiration && bucketInfo1.quota === bucketInfo2.quota && bucketInfo1.persistent === bucketInfo2.persistent && bucketInfo1.durability === bucketInfo2.durability; } storageBucketCreatedOrUpdated({bucketInfo}: Protocol.Storage.StorageBucketCreatedOrUpdatedEvent): void { const curBucket = this.getBucketById(bucketInfo.id); if (curBucket) { if (!this.bucketInfosAreEqual(curBucket, bucketInfo)) { this.bucketChanged(bucketInfo); } } else { this.bucketAdded(bucketInfo); } } storageBucketDeleted({bucketId}: Protocol.Storage.StorageBucketDeletedEvent): void { const curBucket = this.getBucketById(bucketId); if (curBucket) { this.bucketRemoved(curBucket); } else { throw new Error( `Received an event that Storage Bucket '${bucketId}' was deleted, but it wasn't in the StorageBucketsModel.`); } } attributionReportingTriggerRegistered(_event: Protocol.Storage.AttributionReportingTriggerRegisteredEvent): void { } interestGroupAccessed(_event: Protocol.Storage.InterestGroupAccessedEvent): void { } interestGroupAuctionEventOccurred(_event: Protocol.Storage.InterestGroupAuctionEventOccurredEvent): void { } interestGroupAuctionNetworkRequestCreated(_event: Protocol.Storage.InterestGroupAuctionNetworkRequestCreatedEvent): void { } indexedDBListUpdated(_event: Protocol.Storage.IndexedDBListUpdatedEvent): void { } indexedDBContentUpdated(_event: Protocol.Storage.IndexedDBContentUpdatedEvent): void { } cacheStorageListUpdated(_event: Protocol.Storage.CacheStorageListUpdatedEvent): void { } cacheStorageContentUpdated(_event: Protocol.Storage.CacheStorageContentUpdatedEvent): void { } sharedStorageAccessed(_event: Protocol.Storage.SharedStorageAccessedEvent): void { } sharedStorageWorkletOperationExecutionFinished( _event: Protocol.Storage.SharedStorageWorkletOperationExecutionFinishedEvent): void { } attributionReportingSourceRegistered(_event: Protocol.Storage.AttributionReportingSourceRegisteredEvent): void { } attributionReportingReportSent(_event: Protocol.Storage.AttributionReportingReportSentEvent): void { } attributionReportingVerboseDebugReportSent(_event: Protocol.Storage.AttributionReportingVerboseDebugReportSentEvent): void { } } SDKModel.register(StorageBucketsModel, {capabilities: Capability.STORAGE, autostart: false}); export const enum Events { BUCKET_ADDED = 'BucketAdded', BUCKET_REMOVED = 'BucketRemoved', BUCKET_CHANGED = 'BucketChanged', } export interface BucketEvent { model: StorageBucketsModel; bucketInfo: Protocol.Storage.StorageBucketInfo; } export interface EventTypes { [Events.BUCKET_ADDED]: BucketEvent; [Events.BUCKET_REMOVED]: BucketEvent; [Events.BUCKET_CHANGED]: BucketEvent; }