All files / client/src/lib parent-origin.ts

100% Statements 13/13
100% Branches 11/11
100% Functions 2/2
100% Lines 10/10

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32                              15x 15x 6x 15x 5x       5x 4x 4x 4x   1x      
type EmbeddingWindow = {
  readonly parent: unknown;
  readonly location: { readonly origin: string; readonly ancestorOrigins?: ArrayLike<string> };
  readonly document?: { readonly referrer?: string };
};
 
/**
 * Origin of the page that embeds the simulator, used as postMessage peer.
 * `location.ancestorOrigins` is Chromium/WebKit only; Firefox gets the origin from
 * the referrer of the iframe navigation instead. Which pages may embed at all is
 * enforced by the browser through the CSP `frame-ancestors` allowlist, and
 * postMessage delivers only to the exact target origin, so a wrong guess fails
 * closed. Top-level, the simulator's own origin is used, as before.
 */
export function detectParentOrigin(win: EmbeddingWindow = globalThis as unknown as EmbeddingWindow): string {
  const ownOrigin = win.location.origin;
  if (win.parent === win) return ownOrigin;
  const ancestor = win.location.ancestorOrigins?.[0];
  if (ancestor) return ancestor;
  return originOf(win.document?.referrer) ?? ownOrigin;
}
 
function originOf(url: string | undefined): string | undefined {
  if (!url) return undefined;
  try {
    const { origin } = new URL(url);
    return origin === "null" ? undefined : origin;
  } catch {
    return undefined;
  }
}