or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced-web-features.mdbrowser-page-control.mdcore-debugging.mddevice-testing.mddom-styling.mdindex.mdnetwork-performance.mdstorage-data.md
tile.json

storage-data.mddocs/

Storage and Data Management

Browser storage inspection, database analysis, and data persistence debugging. This covers domains that provide access to various browser storage mechanisms including cookies, local storage, IndexedDB, and cache storage.

Capabilities

Storage Domain

Browser storage inspection for analyzing cookies, local storage, session storage, and other storage mechanisms.

namespace Protocol.Storage {
  type SerializedStorageKey = string;
  type StorageType = ('appcache' | 'cookies' | 'file_systems' | 'indexeddb' | 'local_storage' | 'shader_cache' | 'websql' | 'service_workers' | 'cache_storage' | 'interest_groups' | 'shared_storage' | 'storage_buckets' | 'all' | 'other');
  type AttributionReportingSourceType = ('navigation' | 'event');

  interface StorageKey {
    origin?: string;
    topLevelSite?: string;
    nonce?: string;
    ancestorChainBit?: ('SameSite' | 'CrossSite');
  }

  interface UsageForType {
    storageType: StorageType;
    usage: number;
  }

  interface TrustTokens {
    issuerOrigin: string;
    count: number;
  }

  interface SharedStorageEntry {
    key: string;
    value: string;
  }

  interface SharedStorageMetadata {
    creationTime: Network.TimeSinceEpoch;
    length: integer;
    remainingBudget: number;
    bytesUsed: integer;
  }

  interface SharedStorageReportingMetadata {
    eventType: string;
    reportingOrigin: string;
  }

  interface GetStorageKeyForFrameRequest {
    frameId: Page.FrameId;
  }

  interface GetStorageKeyForFrameResponse {
    storageKey: SerializedStorageKey;
  }

  interface ClearDataForOriginRequest {
    origin: string;
    storageTypes: string;
  }

  interface ClearDataForStorageKeyRequest {
    storageKey: SerializedStorageKey;
    storageTypes: string;
  }

  interface GetUsageAndQuotaRequest {
    origin: string;
  }

  interface GetUsageAndQuotaResponse {
    usage: number;
    quota: number;
    overrideActive: boolean;
    usageBreakdown: UsageForType[];
  }

  interface OverrideQuotaForOriginRequest {
    origin: string;
    quotaSize?: number;
  }

  interface TrackCacheStorageForOriginRequest {
    origin: string;
  }

  interface TrackIndexedDBForOriginRequest {
    origin: string;
  }

  interface UntrackCacheStorageForOriginRequest {
    origin: string;
  }

  interface UntrackIndexedDBForOriginRequest {
    origin: string;
  }

  interface GetTrustTokensRequest {
    origin: string;
  }

  interface GetTrustTokensResponse {
    tokens: TrustTokens[];
  }

  interface ClearTrustTokensRequest {
    issuerOrigin: string;
  }

  interface ClearTrustTokensResponse {
    didDeleteTokens: boolean;
  }

  interface CacheStorageContentUpdatedEvent {
    origin: string;
    storageKey: SerializedStorageKey;
    bucketId: string;
    cacheName: string;
  }

  interface CacheStorageListUpdatedEvent {
    origin: string;
    storageKey: SerializedStorageKey;
    bucketId: string;
  }

  interface IndexedDBContentUpdatedEvent {
    origin: string;
    storageKey: SerializedStorageKey;
    bucketId: string;
    databaseName: string;
    objectStoreName: string;
  }

  interface IndexedDBListUpdatedEvent {
    origin: string;
    storageKey: SerializedStorageKey;
    bucketId: string;
  }
}

Usage Example:

import Protocol from "devtools-protocol/types/protocol";

class StorageManager {
  async analyzeStorageUsage(origin: string): Promise<StorageAnalysis> {
    // Get usage and quota information
    const usageRequest: Protocol.Storage.GetUsageAndQuotaRequest = { origin };
    const usageResponse = await this.getUsageAndQuota(usageRequest);

    // Get storage key for current frame
    const storageKeyRequest: Protocol.Storage.GetStorageKeyForFrameRequest = {
      frameId: "main_frame_id"
    };
    const storageKeyResponse = await this.getStorageKeyForFrame(storageKeyRequest);

    return {
      origin,
      totalUsage: usageResponse.usage,
      quota: usageResponse.quota,
      usageBreakdown: usageResponse.usageBreakdown,
      storageKey: storageKeyResponse.storageKey,
      recommendations: this.generateStorageRecommendations(usageResponse)
    };
  }

  private async getUsageAndQuota(request: Protocol.Storage.GetUsageAndQuotaRequest): Promise<Protocol.Storage.GetUsageAndQuotaResponse> {
    // Implementation would send Storage.getUsageAndQuota
    return {
      usage: 1024 * 1024, // 1MB
      quota: 50 * 1024 * 1024, // 50MB
      overrideActive: false,
      usageBreakdown: [
        { storageType: 'indexeddb', usage: 512 * 1024 },
        { storageType: 'local_storage', usage: 256 * 1024 },
        { storageType: 'cache_storage', usage: 256 * 1024 }
      ]
    };
  }

  private async getStorageKeyForFrame(request: Protocol.Storage.GetStorageKeyForFrameRequest): Promise<Protocol.Storage.GetStorageKeyForFrameResponse> {
    // Implementation would send Storage.getStorageKeyForFrame
    return {
      storageKey: "https://example.com"
    };
  }

  async clearStorageForOrigin(origin: string, storageTypes: Protocol.Storage.StorageType[]): Promise<void> {
    const request: Protocol.Storage.ClearDataForOriginRequest = {
      origin,
      storageTypes: storageTypes.join(',')
    };

    // Implementation would send Storage.clearDataForOrigin
  }

  async overrideQuotaForTesting(origin: string, quotaSize: number): Promise<void> {
    const request: Protocol.Storage.OverrideQuotaForOriginRequest = {
      origin,
      quotaSize
    };

    // Implementation would send Storage.overrideQuotaForOrigin
  }

  setupStorageListeners(): void {
    this.onCacheStorageUpdated = (event: Protocol.Storage.CacheStorageContentUpdatedEvent) => {
      console.log(`Cache storage updated for ${event.origin}, cache: ${event.cacheName}`);
    };

    this.onIndexedDBUpdated = (event: Protocol.Storage.IndexedDBContentUpdatedEvent) => {
      console.log(`IndexedDB updated for ${event.origin}, database: ${event.databaseName}`);
    };
  }

  private generateStorageRecommendations(usage: Protocol.Storage.GetUsageAndQuotaResponse): string[] {
    const recommendations: string[] = [];
    const usagePercentage = (usage.usage / usage.quota) * 100;

    if (usagePercentage > 80) {
      recommendations.push("Storage usage is high - consider cleaning up old data");
    }

    const indexedDBUsage = usage.usageBreakdown.find(u => u.storageType === 'indexeddb')?.usage || 0;
    if (indexedDBUsage > usage.usage * 0.5) {
      recommendations.push("IndexedDB is using significant storage - review database size");
    }

    return recommendations;
  }
}

interface StorageAnalysis {
  origin: string;
  totalUsage: number;
  quota: number;
  usageBreakdown: Protocol.Storage.UsageForType[];
  storageKey: string;
  recommendations: string[];
}

IndexedDB Domain

IndexedDB database inspection and analysis for debugging client-side databases.

namespace Protocol.IndexedDB {
  interface DatabaseWithObjectStores {
    name: string;
    version: number;
    objectStores: ObjectStore[];
  }

  interface ObjectStore {
    name: string;
    keyPath: KeyPath;
    autoIncrement: boolean;
    indexes: ObjectStoreIndex[];
  }

  interface ObjectStoreIndex {
    name: string;
    keyPath: KeyPath;
    unique: boolean;
    multiEntry: boolean;
  }

  interface Key {
    type: ('number' | 'string' | 'date' | 'array');
    number?: number;
    string?: string;
    date?: number;
    array?: Key[];
  }

  interface KeyRange {
    lower?: Key;
    upper?: Key;
    lowerOpen: boolean;
    upperOpen: boolean;
  }

  interface KeyPath {
    type: ('null' | 'string' | 'array');
    string?: string;
    array?: string[];
  }

  interface DataEntry {
    key: Runtime.RemoteObject;
    primaryKey: Runtime.RemoteObject;
    value: Runtime.RemoteObject;
  }

  interface GetDatabaseNamesRequest {
    securityOrigin?: string;
    storageKey?: string;
  }

  interface GetDatabaseNamesResponse {
    databaseNames: string[];
  }

  interface RequestDatabaseRequest {
    securityOrigin?: string;
    storageKey?: string;
    databaseName: string;
  }

  interface RequestDatabaseResponse {
    databaseWithObjectStores: DatabaseWithObjectStores;
  }

  interface RequestDataRequest {
    securityOrigin?: string;
    storageKey?: string;
    databaseName: string;
    objectStoreName: string;
    indexName: string;
    skipCount: integer;
    pageSize: integer;
    keyRange?: KeyRange;
  }

  interface RequestDataResponse {
    objectStoreDataEntries: DataEntry[];
    hasMore: boolean;
  }

  interface GetMetadataRequest {
    securityOrigin?: string;
    storageKey?: string;
    databaseName: string;
    objectStoreName: string;
  }

  interface GetMetadataResponse {
    entriesCount: number;
    keyGeneratorValue: number;
  }

  interface DeleteDatabaseRequest {
    securityOrigin?: string;
    storageKey?: string;
    databaseName: string;
  }

  interface ClearObjectStoreRequest {
    securityOrigin?: string;
    storageKey?: string;
    databaseName: string;
    objectStoreName: string;
  }

  interface DeleteObjectStoreEntriesRequest {
    securityOrigin?: string;
    storageKey?: string;
    databaseName: string;
    objectStoreName: string;
    keyRange: KeyRange;
  }
}

Usage Example:

import Protocol from "devtools-protocol/types/protocol";

class IndexedDBInspector {
  async analyzeDatabases(origin: string): Promise<IndexedDBAnalysis> {
    // Get all database names
    const namesRequest: Protocol.IndexedDB.GetDatabaseNamesRequest = {
      securityOrigin: origin
    };
    const databaseNames = await this.getDatabaseNames(namesRequest);

    const databases: DatabaseAnalysis[] = [];

    for (const dbName of databaseNames.databaseNames) {
      const dbAnalysis = await this.analyzeDatabase(origin, dbName);
      databases.push(dbAnalysis);
    }

    return {
      origin,
      databases,
      totalDatabases: databases.length,
      totalObjectStores: databases.reduce((sum, db) => sum + db.objectStores.length, 0)
    };
  }

  private async getDatabaseNames(request: Protocol.IndexedDB.GetDatabaseNamesRequest): Promise<Protocol.IndexedDB.GetDatabaseNamesResponse> {
    // Implementation would send IndexedDB.getDatabaseNames
    return {
      databaseNames: ["userDB", "cacheDB", "settingsDB"]
    };
  }

  private async analyzeDatabase(origin: string, databaseName: string): Promise<DatabaseAnalysis> {
    // Get database structure
    const dbRequest: Protocol.IndexedDB.RequestDatabaseRequest = {
      securityOrigin: origin,
      databaseName
    };
    const dbResponse = await this.requestDatabase(dbRequest);

    const objectStores: ObjectStoreAnalysis[] = [];

    for (const store of dbResponse.databaseWithObjectStores.objectStores) {
      const storeAnalysis = await this.analyzeObjectStore(origin, databaseName, store);
      objectStores.push(storeAnalysis);
    }

    return {
      name: databaseName,
      version: dbResponse.databaseWithObjectStores.version,
      objectStores
    };
  }

  private async requestDatabase(request: Protocol.IndexedDB.RequestDatabaseRequest): Promise<Protocol.IndexedDB.RequestDatabaseResponse> {
    // Implementation would send IndexedDB.requestDatabase
    return {
      databaseWithObjectStores: {
        name: "userDB",
        version: 1,
        objectStores: [
          {
            name: "users",
            keyPath: { type: 'string', string: 'id' },
            autoIncrement: false,
            indexes: [
              {
                name: "email",
                keyPath: { type: 'string', string: 'email' },
                unique: true,
                multiEntry: false
              }
            ]
          }
        ]
      }
    };
  }

  private async analyzeObjectStore(origin: string, databaseName: string, store: Protocol.IndexedDB.ObjectStore): Promise<ObjectStoreAnalysis> {
    // Get metadata
    const metadataRequest: Protocol.IndexedDB.GetMetadataRequest = {
      securityOrigin: origin,
      databaseName,
      objectStoreName: store.name
    };
    const metadata = await this.getMetadata(metadataRequest);

    // Get sample data
    const dataRequest: Protocol.IndexedDB.RequestDataRequest = {
      securityOrigin: origin,
      databaseName,
      objectStoreName: store.name,
      indexName: "",
      skipCount: 0,
      pageSize: 10
    };
    const data = await this.requestData(dataRequest);

    return {
      name: store.name,
      keyPath: store.keyPath,
      autoIncrement: store.autoIncrement,
      indexes: store.indexes,
      entriesCount: metadata.entriesCount,
      keyGeneratorValue: metadata.keyGeneratorValue,
      sampleData: data.objectStoreDataEntries.slice(0, 5) // First 5 entries
    };
  }

  private async getMetadata(request: Protocol.IndexedDB.GetMetadataRequest): Promise<Protocol.IndexedDB.GetMetadataResponse> {
    // Implementation would send IndexedDB.getMetadata
    return {
      entriesCount: 150,
      keyGeneratorValue: 151
    };
  }

  private async requestData(request: Protocol.IndexedDB.RequestDataRequest): Promise<Protocol.IndexedDB.RequestDataResponse> {
    // Implementation would send IndexedDB.requestData
    return {
      objectStoreDataEntries: [],
      hasMore: false
    };
  }

  async deleteDatabase(origin: string, databaseName: string): Promise<void> {
    const request: Protocol.IndexedDB.DeleteDatabaseRequest = {
      securityOrigin: origin,
      databaseName
    };

    // Implementation would send IndexedDB.deleteDatabase
  }

  async clearObjectStore(origin: string, databaseName: string, objectStoreName: string): Promise<void> {
    const request: Protocol.IndexedDB.ClearObjectStoreRequest = {
      securityOrigin: origin,
      databaseName,
      objectStoreName
    };

    // Implementation would send IndexedDB.clearObjectStore
  }

  async queryObjectStore(origin: string, databaseName: string, objectStoreName: string, keyRange?: Protocol.IndexedDB.KeyRange): Promise<Protocol.IndexedDB.DataEntry[]> {
    const request: Protocol.IndexedDB.RequestDataRequest = {
      securityOrigin: origin,
      databaseName,
      objectStoreName,
      indexName: "",
      skipCount: 0,
      pageSize: 100,
      keyRange
    };

    const response = await this.requestData(request);
    return response.objectStoreDataEntries;
  }
}

interface IndexedDBAnalysis {
  origin: string;
  databases: DatabaseAnalysis[];
  totalDatabases: number;
  totalObjectStores: number;
}

interface DatabaseAnalysis {
  name: string;
  version: number;
  objectStores: ObjectStoreAnalysis[];
}

interface ObjectStoreAnalysis {
  name: string;
  keyPath: Protocol.IndexedDB.KeyPath;
  autoIncrement: boolean;
  indexes: Protocol.IndexedDB.ObjectStoreIndex[];
  entriesCount: number;
  keyGeneratorValue: number;
  sampleData: Protocol.IndexedDB.DataEntry[];
}

DOMStorage Domain

Local and session storage management for analyzing key-value storage.

namespace Protocol.DOMStorage {
  type StorageId = {
    securityOrigin: string;
    storageKey?: Storage.SerializedStorageKey;
    isLocalStorage: boolean;
  };

  interface Item = [string, string];

  interface GetDOMStorageItemsRequest {
    storageId: StorageId;
  }

  interface GetDOMStorageItemsResponse {
    entries: Item[];
  }

  interface SetDOMStorageItemRequest {
    storageId: StorageId;
    key: string;
    value: string;
  }

  interface RemoveDOMStorageItemRequest {
    storageId: StorageId;
    key: string;
  }

  interface ClearDOMStorageRequest {
    storageId: StorageId;
  }

  interface DomStorageItemsClearedEvent {
    storageId: StorageId;
  }

  interface DomStorageItemRemovedEvent {
    storageId: StorageId;
    key: string;
  }

  interface DomStorageItemAddedEvent {
    storageId: StorageId;
    key: string;
    newValue: string;
  }

  interface DomStorageItemUpdatedEvent {
    storageId: StorageId;
    key: string;
    oldValue: string;
    newValue: string;
  }
}

CacheStorage Domain

Cache API storage management for analyzing cached responses.

namespace Protocol.CacheStorage {
  interface Cache {
    cacheId: CacheId;
    securityOrigin: string;
    storageKey: string;
    storageBucket?: StorageBucket;
    cacheName: string;
  }

  interface Header {
    name: string;
    value: string;
  }

  interface CachedResponse {
    body: string;
  }

  interface DataEntry {
    requestURL: string;
    requestMethod: string;
    requestHeaders: Header[];
    responseTime: number;
    responseStatus: integer;
    responseStatusText: string;
    responseType: ('basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect');
    responseHeaders: Header[];
  }

  type CacheId = string;

  interface RequestCacheNamesRequest {
    securityOrigin?: string;
    storageKey?: string;
    storageBucket?: StorageBucket;
  }

  interface RequestCacheNamesResponse {
    caches: Cache[];
  }

  interface RequestCachedResponseRequest {
    cacheId: CacheId;
    requestURL: string;
    requestHeaders: Header[];
  }

  interface RequestCachedResponseResponse {
    response: CachedResponse;
  }

  interface RequestEntriesRequest {
    cacheId: CacheId;
    skipCount?: integer;
    pageSize?: integer;
    pathFilter?: string;
  }

  interface RequestEntriesResponse {
    cacheDataEntries: DataEntry[];
    returnCount: number;
  }

  interface DeleteCacheRequest {
    cacheId: CacheId;
  }

  interface DeleteEntryRequest {
    cacheId: CacheId;
    request: string;
  }

  interface PutEntryRequest {
    cacheId: CacheId;
    request: string;
    response: CachedResponse;
  }
}

Common Usage Patterns

Comprehensive Storage Analysis

import Protocol from "devtools-protocol/types/protocol";

class StorageAnalyzer {
  private storageManager: StorageManager;
  private indexedDBInspector: IndexedDBInspector;

  constructor() {
    this.storageManager = new StorageManager();
    this.indexedDBInspector = new IndexedDBInspector();
  }

  async performCompleteStorageAnalysis(origin: string): Promise<CompleteStorageAnalysis> {
    // Analyze overall storage usage
    const storageAnalysis = await this.storageManager.analyzeStorageUsage(origin);
    
    // Analyze IndexedDB
    const indexedDBAnalysis = await this.indexedDBInspector.analyzeDatabases(origin);
    
    // Analyze DOM storage
    const domStorageAnalysis = await this.analyzeDOMStorage(origin);
    
    // Analyze Cache Storage
    const cacheStorageAnalysis = await this.analyzeCacheStorage(origin);
    
    return {
      origin,
      overall: storageAnalysis,
      indexedDB: indexedDBAnalysis,
      domStorage: domStorageAnalysis,
      cacheStorage: cacheStorageAnalysis,
      recommendations: this.generateComprehensiveRecommendations({
        storageAnalysis,
        indexedDBAnalysis,
        domStorageAnalysis,
        cacheStorageAnalysis
      })
    };
  }

  private async analyzeDOMStorage(origin: string): Promise<DOMStorageAnalysis> {
    const localStorageId: Protocol.DOMStorage.StorageId = {
      securityOrigin: origin,
      isLocalStorage: true
    };

    const sessionStorageId: Protocol.DOMStorage.StorageId = {
      securityOrigin: origin,
      isLocalStorage: false
    };

    // Get localStorage items
    const localStorageRequest: Protocol.DOMStorage.GetDOMStorageItemsRequest = {
      storageId: localStorageId
    };

    // Get sessionStorage items
    const sessionStorageRequest: Protocol.DOMStorage.GetDOMStorageItemsRequest = {
      storageId: sessionStorageId
    };

    // Implementation would get actual storage items
    const localStorage: Protocol.DOMStorage.Item[] = [
      ["user_preferences", '{"theme":"dark","language":"en"}'],
      ["cached_data", "...large data..."]
    ];

    const sessionStorage: Protocol.DOMStorage.Item[] = [
      ["session_token", "abc123"],
      ["temp_data", "temporary value"]
    ];

    return {
      localStorage: {
        items: localStorage,
        count: localStorage.length,
        totalSize: this.calculateStorageSize(localStorage)
      },
      sessionStorage: {
        items: sessionStorage,
        count: sessionStorage.length,
        totalSize: this.calculateStorageSize(sessionStorage)
      }
    };
  }

  private async analyzeCacheStorage(origin: string): Promise<CacheStorageAnalysis> {
    const cacheNamesRequest: Protocol.CacheStorage.RequestCacheNamesRequest = {
      securityOrigin: origin
    };

    // Implementation would get cache names
    const caches: Protocol.CacheStorage.Cache[] = [
      {
        cacheId: "cache1",
        securityOrigin: origin,
        storageKey: origin,
        cacheName: "api-cache"
      },
      {
        cacheId: "cache2",
        securityOrigin: origin,
        storageKey: origin,
        cacheName: "assets-cache"
      }
    ];

    const cacheAnalyses: CacheAnalysis[] = [];

    for (const cache of caches) {
      const entriesRequest: Protocol.CacheStorage.RequestEntriesRequest = {
        cacheId: cache.cacheId,
        pageSize: 100
      };

      // Implementation would get cache entries
      const entries: Protocol.CacheStorage.DataEntry[] = [];

      cacheAnalyses.push({
        name: cache.cacheName,
        id: cache.cacheId,
        entryCount: entries.length,
        totalSize: entries.reduce((sum, entry) => sum + (entry.requestURL.length + entry.responseStatusText.length), 0),
        entries: entries.slice(0, 10) // Sample entries
      });
    }

    return {
      caches: cacheAnalyses,
      totalCaches: caches.length,
      totalEntries: cacheAnalyses.reduce((sum, cache) => sum + cache.entryCount, 0)
    };
  }

  private calculateStorageSize(items: Protocol.DOMStorage.Item[]): number {
    return items.reduce((sum, [key, value]) => sum + key.length + value.length, 0);
  }

  private generateComprehensiveRecommendations(analyses: {
    storageAnalysis: StorageAnalysis;
    indexedDBAnalysis: IndexedDBAnalysis;
    domStorageAnalysis: DOMStorageAnalysis;
    cacheStorageAnalysis: CacheStorageAnalysis;
  }): string[] {
    const recommendations: string[] = [];

    // Overall storage recommendations
    recommendations.push(...analyses.storageAnalysis.recommendations);

    // IndexedDB recommendations
    if (analyses.indexedDBAnalysis.totalDatabases > 5) {
      recommendations.push("Consider consolidating IndexedDB databases - high database count detected");
    }

    // DOM storage recommendations
    const totalDOMStorageSize = analyses.domStorageAnalysis.localStorage.totalSize + 
                               analyses.domStorageAnalysis.sessionStorage.totalSize;
    if (totalDOMStorageSize > 5 * 1024 * 1024) { // 5MB
      recommendations.push("DOM storage usage is high - consider moving large data to IndexedDB");
    }

    // Cache storage recommendations
    if (analyses.cacheStorageAnalysis.totalCaches > 10) {
      recommendations.push("High number of caches - consider cache cleanup strategy");
    }

    return recommendations;
  }

  async cleanupStorage(origin: string, cleanupOptions: StorageCleanupOptions): Promise<StorageCleanupResults> {
    const results: StorageCleanupResults = {
      success: true,
      cleaned: [],
      errors: []
    };

    try {
      if (cleanupOptions.clearDOMStorage) {
        await this.clearDOMStorage(origin);
        results.cleaned.push("DOM Storage");
      }

      if (cleanupOptions.clearIndexedDB) {
        await this.clearIndexedDB(origin);
        results.cleaned.push("IndexedDB");
      }

      if (cleanupOptions.clearCacheStorage) {
        await this.clearCacheStorage(origin);
        results.cleaned.push("Cache Storage");
      }

      if (cleanupOptions.storageTypes && cleanupOptions.storageTypes.length > 0) {
        await this.storageManager.clearStorageForOrigin(origin, cleanupOptions.storageTypes);
        results.cleaned.push(`Additional storage types: ${cleanupOptions.storageTypes.join(', ')}`);
      }
    } catch (error) {
      results.success = false;
      results.errors.push(error.message);
    }

    return results;
  }

  private async clearDOMStorage(origin: string): Promise<void> {
    const localStorageId: Protocol.DOMStorage.StorageId = {
      securityOrigin: origin,
      isLocalStorage: true
    };

    const sessionStorageId: Protocol.DOMStorage.StorageId = {
      securityOrigin: origin,
      isLocalStorage: false
    };

    const clearLocalRequest: Protocol.DOMStorage.ClearDOMStorageRequest = {
      storageId: localStorageId
    };

    const clearSessionRequest: Protocol.DOMStorage.ClearDOMStorageRequest = {
      storageId: sessionStorageId
    };

    // Implementation would send DOMStorage.clear commands
  }

  private async clearIndexedDB(origin: string): Promise<void> {
    const indexedDBAnalysis = await this.indexedDBInspector.analyzeDatabases(origin);
    
    for (const db of indexedDBAnalysis.databases) {
      await this.indexedDBInspector.deleteDatabase(origin, db.name);
    }
  }

  private async clearCacheStorage(origin: string): Promise<void> {
    const cacheNamesRequest: Protocol.CacheStorage.RequestCacheNamesRequest = {
      securityOrigin: origin
    };

    // Implementation would get cache names and delete each cache
  }
}

interface CompleteStorageAnalysis {
  origin: string;
  overall: StorageAnalysis;
  indexedDB: IndexedDBAnalysis;
  domStorage: DOMStorageAnalysis;
  cacheStorage: CacheStorageAnalysis;
  recommendations: string[];
}

interface DOMStorageAnalysis {
  localStorage: {
    items: Protocol.DOMStorage.Item[];
    count: number;
    totalSize: number;
  };
  sessionStorage: {
    items: Protocol.DOMStorage.Item[];
    count: number;
    totalSize: number;
  };
}

interface CacheStorageAnalysis {
  caches: CacheAnalysis[];
  totalCaches: number;
  totalEntries: number;
}

interface CacheAnalysis {
  name: string;
  id: string;
  entryCount: number;
  totalSize: number;
  entries: Protocol.CacheStorage.DataEntry[];
}

interface StorageCleanupOptions {
  clearDOMStorage?: boolean;
  clearIndexedDB?: boolean;
  clearCacheStorage?: boolean;
  storageTypes?: Protocol.Storage.StorageType[];
}

interface StorageCleanupResults {
  success: boolean;
  cleaned: string[];
  errors: string[];
}