Signatur
Beschreibung
Die Eigenschaft ancestorOrigins des Interface WindowClient liefert im Service Worker ein eingefrorenes Array von Zeichenketten. Es enthält die Ursprünge (origins) aller übergeordneten Browsing-Kontexte des Clients. Das erste Element ist der Ursprung des direkten Elternfensters, das letzte der Ursprung des obersten Fensters (top-level). Wenn der Client selbst ein Hauptfenster ist, ist das Array leer.
So erfährt ein Service Worker, ob eine kontrollierte Seite in einem <iframe> läuft und von welcher Website sie eingebettet wird. Das Fensterobjekt muss dafür nicht erreichbar sein. Typische Anwendungen sind Einbettungsrichtlinien (nur bestimmte Partner-Domains dürfen einbetten), Analysen oder unterschiedliche Antworten für eingebettete und eigenständige Fenster.
Die Eigenschaft entspricht Location.ancestorOrigins im Fensterkontext. Man liest sie meist an Clients aus, die man über clients.matchAll({ type: "window" }) oder clients.get(id) erhält.
Rückgabewert
"https://example.com". Die Reihenfolge reicht vom direkten Elternfenster bis zum obersten Fenster. Bei einem Hauptfenster ist das Array leer ([]).Beispiele
Eingebettete Fenster-Clients im Service Worker auflisten
// sw.js
self.addEventListener("message", async (event) => {
if (event.data !== "list-clients") return;
const windows = await self.clients.matchAll({ type: "window", includeUncontrolled: true });
for (const client of windows) {
const ancestors = client.ancestorOrigins ?? [];
const embedded = ancestors.length > 0;
console.log(client.url, embedded ? `eingebettet von ${ancestors.join(" → ")}` : "Hauptfenster");
}
});
Einbettung nur durch erlaubte Ursprünge zulassen
// sw.js
const ERLAUBT = new Set(["https://app.example.com", "https://partner.de"]);
self.addEventListener("fetch", (event) => {
if (event.request.mode !== "navigate") return;
event.respondWith((async () => {
const clientId = event.resultingClientId || event.clientId;
const client = clientId ? await self.clients.get(clientId) : null;
const ancestors = client?.ancestorOrigins ?? [];
const unerlaubt = ancestors.some((origin) => !ERLAUBT.has(origin));
if (unerlaubt) {
return new Response("Einbettung nicht erlaubt", { status: 403 });
}
return fetch(event.request);
})());
});
Oberstes Fenster ermitteln und Feature-Erkennung
// sw.js
const topOrigin = (client) => {
if (!("ancestorOrigins" in WindowClient.prototype)) return undefined; // nicht unterstützt
const list = client.ancestorOrigins;
return list.length ? list[list.length - 1] : new URL(client.url).origin;
};
self.addEventListener("activate", async () => {
const windows = await self.clients.matchAll({ type: "window" });
windows.forEach((c) => console.log(c.id, topOrigin(c)));
});
// Wichtig · Fallstricke
- Eingeschränkte Unterstützung: Die Eigenschaft gibt es nur in Chromium-Browsern. In Firefox und Safari ist sie
undefined. Deshalb immer eine Feature-Erkennung verwenden ("ancestorOrigins" in WindowClient.prototype) oder auf?? []zurückfallen. - Keine Sicherheitsgarantie allein: Einträge können
"null"lauten, etwa bei Sandbox-iframes oder beireferrerpolicy="no-referrer"am<iframe>. Außerdem fehlt die Information in manchen Browsern ganz. Für verbindlichen Schutz vor Clickjacking gehört der CSP-Headerframe-ancestorsauf den Server. - Die Reihenfolge beginnt beim direkten Elternfenster. Das oberste Fenster ist also das letzte Element, nicht das erste.
- Das Array ist eingefroren. Zuweisungen oder
push()werfen im Strict Mode einen Fehler oder schlagen stillschweigend fehl. - Die Eigenschaft ist nur im Service-Worker-Kontext an
WindowClient-Objekten verfügbar. EinfacheClient-Objekte (z. B. von Workern) haben sie nicht.