UNPKG

chrome-devtools-frontend

Version:
201 lines (177 loc) • 8.73 kB
// Copyright 2023 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import type * as Common from '../../core/common/common.js'; import * as i18n from '../../core/i18n/i18n.js'; import type * as Platform from '../../core/platform/platform.js'; import * as SDK from '../../core/sdk/sdk.js'; import type * as Protocol from '../../generated/protocol.js'; import * as IconButton from '../../ui/components/icon_button/icon_button.js'; import * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js'; import * as UI from '../../ui/legacy/legacy.js'; import {IndexedDBTreeElement} from './ApplicationPanelSidebar.js'; import {ExpandableApplicationPanelTreeElement} from './ApplicationPanelTreeElement.js'; import {StorageMetadataView} from './components/components.js'; import type {ResourcesPanel} from './ResourcesPanel.js'; import {ServiceWorkerCacheTreeElement} from './ServiceWorkerCacheTreeElement.js'; const UIStrings = { /** *@description Label for an item in the Application Panel Sidebar of the Application panel * Storage Buckets allow developers to separate site data into buckets so that they can be * deleted independently. */ storageBuckets: 'Storage buckets', /** *@description Text for an item in the Application Panel * if no storage buckets are available to show. Storage Buckets allow developers to separate * site data into buckets so that they can be * deleted independently. https://developer.chrome.com/docs/web-platform/storage-buckets. */ noStorageBuckets: 'No storage buckets detected', /** *@description Description text in the Application Panel describing the storage buckets tab. * Storage Buckets allow developers to separate site data into buckets so that they can be * deleted independently. https://developer.chrome.com/docs/web-platform/storage-buckets. */ storageBucketsDescription: 'On this page you can view and delete storage buckets, and their associated `Storage APIs`.' } as const; const str_ = i18n.i18n.registerUIStrings('panels/application/StorageBucketsTreeElement.ts', UIStrings); export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class StorageBucketsTreeParentElement extends ExpandableApplicationPanelTreeElement { private bucketTreeElements = new Set<StorageBucketsTreeElement>(); constructor(storagePanel: ResourcesPanel) { super( storagePanel, i18nString(UIStrings.storageBuckets), i18nString(UIStrings.noStorageBuckets), i18nString(UIStrings.storageBucketsDescription), 'storage-buckets'); const icon = IconButton.Icon.create('database'); this.setLeadingIcons([icon]); this.setLink( 'https://github.com/WICG/storage-buckets/blob/gh-pages/explainer.md' as Platform.DevToolsPath.UrlString); } initialize(): void { SDK.TargetManager.TargetManager.instance().addModelListener( SDK.StorageBucketsModel.StorageBucketsModel, SDK.StorageBucketsModel.Events.BUCKET_ADDED, this.bucketAdded, this); SDK.TargetManager.TargetManager.instance().addModelListener( SDK.StorageBucketsModel.StorageBucketsModel, SDK.StorageBucketsModel.Events.BUCKET_REMOVED, this.bucketRemoved, this); SDK.TargetManager.TargetManager.instance().addModelListener( SDK.StorageBucketsModel.StorageBucketsModel, SDK.StorageBucketsModel.Events.BUCKET_CHANGED, this.bucketChanged, this); for (const bucketsModel of SDK.TargetManager.TargetManager.instance().models( SDK.StorageBucketsModel.StorageBucketsModel)) { const buckets = bucketsModel.getBuckets(); for (const bucket of buckets) { this.addBucketTreeElement(bucketsModel, bucket); } } } removeBucketsForModel(model: SDK.StorageBucketsModel.StorageBucketsModel): void { for (const bucketTreeElement of this.bucketTreeElements) { if (bucketTreeElement.model === model) { this.removeBucketTreeElement(bucketTreeElement); } } } private bucketAdded({data: {model, bucketInfo}}: Common.EventTarget.EventTargetEvent<SDK.StorageBucketsModel.BucketEvent>): void { this.addBucketTreeElement(model, bucketInfo); } private bucketRemoved({data: {model, bucketInfo}}: Common.EventTarget.EventTargetEvent<SDK.StorageBucketsModel.BucketEvent>): void { const idbDatabaseTreeElement = this.getBucketTreeElement(model, bucketInfo); if (!idbDatabaseTreeElement) { return; } this.removeBucketTreeElement(idbDatabaseTreeElement); } private bucketChanged({data: {model, bucketInfo}}: Common.EventTarget.EventTargetEvent<SDK.StorageBucketsModel.BucketEvent>): void { const idbDatabaseTreeElement = this.getBucketTreeElement(model, bucketInfo); if (!idbDatabaseTreeElement) { return; } idbDatabaseTreeElement.bucketInfo = bucketInfo; } private addBucketTreeElement( model: SDK.StorageBucketsModel.StorageBucketsModel, bucketInfo: Protocol.Storage.StorageBucketInfo): void { if (bucketInfo.bucket.name === undefined) { return; } const singleBucketTreeElement = new StorageBucketsTreeElement(this.resourcesPanel, model, bucketInfo); this.bucketTreeElements.add(singleBucketTreeElement); this.appendChild(singleBucketTreeElement); singleBucketTreeElement.initialize(); } private removeBucketTreeElement(bucketTreeElement: StorageBucketsTreeElement): void { this.removeChild(bucketTreeElement); this.bucketTreeElements.delete(bucketTreeElement); this.setExpandable(this.bucketTreeElements.size > 0); } override get itemURL(): Platform.DevToolsPath.UrlString { return 'storage-buckets-group://' as Platform.DevToolsPath.UrlString; } getBucketTreeElement(model: SDK.StorageBucketsModel.StorageBucketsModel, { bucket: {storageKey, name}, }: Protocol.Storage.StorageBucketInfo): StorageBucketsTreeElement|null { for (const bucketTreeElement of this.bucketTreeElements) { if (bucketTreeElement.model === model && bucketTreeElement.bucketInfo.bucket.storageKey === storageKey && bucketTreeElement.bucketInfo.bucket.name === name) { return bucketTreeElement; } } return null; } } export class StorageBucketsTreeElement extends ExpandableApplicationPanelTreeElement { private storageBucketInfo: Protocol.Storage.StorageBucketInfo; private bucketModel: SDK.StorageBucketsModel.StorageBucketsModel; private view?: LegacyWrapper.LegacyWrapper.LegacyWrapper<UI.Widget.Widget, StorageMetadataView.StorageMetadataView>; constructor( resourcesPanel: ResourcesPanel, model: SDK.StorageBucketsModel.StorageBucketsModel, bucketInfo: Protocol.Storage.StorageBucketInfo) { const {bucket} = bucketInfo; const {origin} = SDK.StorageKeyManager.parseStorageKey(bucketInfo.bucket.storageKey); super(resourcesPanel, `${bucket.name} - ${origin}`, '', '', 'storage-bucket'); this.bucketModel = model; this.storageBucketInfo = bucketInfo; const icon = IconButton.Icon.create('database'); this.setLeadingIcons([icon]); } initialize(): void { const {bucket} = this.bucketInfo; const indexedDBTreeElement = new IndexedDBTreeElement(this.resourcesPanel, bucket); this.appendChild(indexedDBTreeElement); const serviceWorkerCacheTreeElement = new ServiceWorkerCacheTreeElement(this.resourcesPanel, bucket); this.appendChild(serviceWorkerCacheTreeElement); serviceWorkerCacheTreeElement.initialize(); } override get itemURL(): Platform.DevToolsPath.UrlString { const {bucket} = this.bucketInfo; return `storage-buckets-group://${bucket.name}/${bucket.storageKey}` as Platform.DevToolsPath.UrlString; } get model(): SDK.StorageBucketsModel.StorageBucketsModel { return this.bucketModel; } get bucketInfo(): Protocol.Storage.StorageBucketInfo { return this.storageBucketInfo; } set bucketInfo(bucketInfo: Protocol.Storage.StorageBucketInfo) { this.storageBucketInfo = bucketInfo; if (this.view) { this.view.getComponent().setStorageBucket(this.storageBucketInfo); } } override onselect(selectedByUser?: boolean): boolean { super.onselect(selectedByUser); if (!this.view) { this.view = LegacyWrapper.LegacyWrapper.legacyWrapper(UI.Widget.Widget, new StorageMetadataView.StorageMetadataView()); this.view.getComponent().enableStorageBucketControls(this.model); this.view.getComponent().setStorageBucket(this.storageBucketInfo); } this.showView(this.view); return false; } }