Start · Sprachen · JavaScript · Referenz · StorageAccessHandle

StorageAccessHandle

Schnittstelle

Gibt eingebetteten Drittanbieter-Inhalten Zugriff auf unpartitionierten Speicher (localStorage, IndexedDB, Caches u. a.), nachdem <code>document.requestStorageAccess()</code> mit Optionen erfolgreich war.

seit JavaScript Chrome/Edge 125+ (experimentell, nicht in Firefox Kategorie: webapi

Signatur

interface StorageAccessHandle

Beschreibung

Browser trennen den Speicher von Drittanbieter-Kontexten (z. B. einem <iframe> von widget.example auf shop.example) zunehmend nach der Website der obersten Ebene auf. Man spricht von Speicherpartitionierung. Mit der Storage Access API kann ein eingebettetes Dokument den Zugriff auf seine unpartitionierten Cookies anfordern. StorageAccessHandle erweitert das auf weitere Speichermechanismen. Diese Erweiterung wird auch „Storage Access API: Beyond Cookies“ genannt.

Einen StorageAccessHandle legst du nicht selbst an. Du bekommst ihn als Ergebnis des Promise von document.requestStorageAccess(types), wenn du ein Options-Objekt übergibst. Ohne Argument löst das Promise dagegen mit undefined auf und gibt nur Cookie-Zugriff frei.

Der Handle stellt die freigegebenen Speicher-APIs als Eigenschaften und Methoden bereit:

  • Eigenschaften: localStorage, sessionStorage, indexedDB, caches, locks
  • Methoden: getDirectory() (Origin Private File System), estimate() (Speicherkontingent), createObjectURL(), revokeObjectURL(), BroadcastChannel(name), SharedWorker(url, options)

Einsetzen solltest du das bei eingebetteten Diensten wie Chat-Widgets, Single-Sign-on, Kommentarsystemen oder Bezahl-iFrames. Sie müssen Zustand teilen, der auch außerhalb der aktuellen Einbettung gilt. Frage nur die Speichertypen an, die du wirklich brauchst: Wenn du auf einen nicht angeforderten Typ zugreifst, wird ein SecurityError geworfen.

Parameter

Name Typ Default Beschreibung
$types Pflicht object Options-Objekt für document.requestStorageAccess(types). Es legt fest, welche Mitglieder des Handles nutzbar sind. Mindestens ein Schlüssel muss true sein, sonst wird das Promise abgelehnt.
$types.all boolean false Fordert alle unten genannten Speichertypen auf einmal an.
$types.cookies boolean false Unpartitionierte Cookies (wie beim Aufruf ohne Argument).
$types.localStorage boolean false Macht handle.localStorage nutzbar.
$types.sessionStorage boolean false Macht handle.sessionStorage nutzbar.
$types.indexedDB boolean false Macht handle.indexedDB nutzbar.
$types.caches boolean false Macht handle.caches (CacheStorage) nutzbar.
$types.locks boolean false Macht handle.locks (Web Locks API) nutzbar.
$types.getDirectory / estimate / createObjectURL / revokeObjectURL / BroadcastChannel / SharedWorker boolean false Schaltet jeweils die gleichnamige Methode des Handles frei.

Rückgabewert

Typ
Promise<StorageAccessHandle>
Beschreibung
document.requestStorageAccess(types) löst mit einem StorageAccessHandle auf, dessen angeforderte Mitglieder auf den unpartitionierten Speicher zeigen. Wird der Zugriff verweigert, lehnt das Promise mit einem NotAllowedError ab.

Beispiele

Unpartitioniertes localStorage im iframe anfordern

// Läuft in einem Drittanbieter-iframe, ausgelöst durch einen Klick (Nutzeraktivierung)
const button = document.querySelector('#login-status');

button.addEventListener('click', async () => {
  try {
    const handle = await document.requestStorageAccess({ localStorage: true });
    const token = handle.localStorage.getItem('sessionToken');
    console.log(token ? 'Angemeldet' : 'Nicht angemeldet');
  } catch (err) {
    console.warn('Speicherzugriff verweigert:', err.name);
  }
});
Angemeldet

Mehrere Speichertypen: IndexedDB und BroadcastChannel

const openSharedState = async () => {
  const handle = await document.requestStorageAccess({
    indexedDB: true,
    BroadcastChannel: true,
  });

  // Unpartitionierte IndexedDB öffnen
  const request = handle.indexedDB.open('widget-db', 1);
  request.onupgradeneeded = () => request.result.createObjectStore('prefs');
  request.onsuccess = () => console.log('DB geöffnet:', request.result.name);

  // Kanal, der auch Top-Level-Tabs von widget.example erreicht
  const channel = handle.BroadcastChannel('widget-sync');
  channel.postMessage({ type: 'hello' });
};

document.querySelector('#sync').addEventListener('click', openSharedState);
DB geöffnet: widget-db

Vorab-Prüfung mit hasStorageAccess und Feature-Erkennung

const getStorage = async () => {
  if (!('requestStorageAccess' in document)) {
    return window.localStorage; // Browser ohne Storage Access API
  }
  // Ist der Zugriff schon erteilt (z. B. per Permission), klappt der Aufruf ohne neue Nachfrage
  const permission = await navigator.permissions
    .query({ name: 'storage-access' })
    .catch(() => null);

  if (permission?.state === 'granted' || navigator.userActivation?.isActive) {
    try {
      const handle = await document.requestStorageAccess({ localStorage: true });
      return handle.localStorage;
    } catch {
      // Fallback weiter unten
    }
  }
  return window.localStorage; // partitionierter Speicher
};

getStorage().then((storage) => console.log(storage.length));
3

Zugriff auf nicht angeforderten Typ wirft Fehler

const demo = async () => {
  const handle = await document.requestStorageAccess({ localStorage: true });
  try {
    handle.sessionStorage.setItem('x', '1'); // nicht angefordert!
  } catch (err) {
    console.log(err.name);
  }
};

document.body.addEventListener('click', demo, { once: true });
SecurityError