fix: isolate multi-embed resize handshake with per-snippet token
ForRelease mints a per-call token used as the iframe id and threaded into the src as EmbedId; the host script matches on it so multiple embeds resize independently. ForTrack unchanged.
This commit is contained in:
@@ -23,6 +23,17 @@ namespace DeepDrftPublic.Client.Helpers;
|
||||
/// outer resize is lost. The track snippet needs no script (no panel, no toggle).
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// Multi-embed isolation: each <see cref="ForRelease"/> call mints a fresh random token (8 hex
|
||||
/// chars). The token is used as the iframe id (<c>deepdrft-embed-{token}</c>) and threaded into
|
||||
/// the iframe src as <c>&EmbedId={token}</c> so the iframe can learn its own id. The host-side
|
||||
/// resize script matches incoming messages on <c>embedId</c> and resizes only the iframe whose id
|
||||
/// matches the token — two releases on one host page resize independently without cross-talk. Two
|
||||
/// calls for the same release still get distinct tokens, ensuring uniqueness even when the same
|
||||
/// release is pasted twice. Older snippets that lack <c>embedId</c> in their postMessage payload are
|
||||
/// silently ignored by the script (backward-compatible degradation).
|
||||
/// </para>
|
||||
///
|
||||
/// Pure string composition so the snippet shape is unit-testable without rendering the component.
|
||||
/// </summary>
|
||||
public static class EmbedSnippetBuilder
|
||||
@@ -39,14 +50,27 @@ public static class EmbedSnippetBuilder
|
||||
=> Frame($"{baseUri}FramePlayer?TrackEntryKey={trackEntryKey}", TrackHeight);
|
||||
|
||||
public static string ForRelease(string baseUri, string releaseEntryKey)
|
||||
=> Frame($"{baseUri}FramePlayer?ReleaseEntryKey={releaseEntryKey}", ReleaseHeight, ResizeScript);
|
||||
{
|
||||
// Mint a fresh random token per call so two embeds on the same host page never share an id,
|
||||
// even when they point at the same release.
|
||||
var token = Guid.NewGuid().ToString("N")[..8];
|
||||
var iframeId = $"deepdrft-embed-{token}";
|
||||
var src = $"{baseUri}FramePlayer?ReleaseEntryKey={releaseEntryKey}&EmbedId={token}";
|
||||
return Frame(src, ReleaseHeight, iframeId, ResizeScript(iframeId, token));
|
||||
}
|
||||
|
||||
private static string Frame(string src, int height, string trailingScript = "")
|
||||
=> $"""<iframe id="deepdrft-embed" src="{src}" width="656" height="{height}" frameborder="0" style="border-radius:8px;" allow="autoplay"></iframe>{trailingScript}""";
|
||||
private static string Frame(string src, int height, string iframeId = "deepdrft-embed", string trailingScript = "")
|
||||
=> $"""<iframe id="{iframeId}" src="{src}" width="656" height="{height}" frameborder="0" style="border-radius:8px;" allow="autoplay"></iframe>{trailingScript}""";
|
||||
|
||||
// Host-side listener: resize #deepdrft-embed when the embedded player posts its panel height. The
|
||||
// shape/origin-agnostic guard (ignores non-matching messages) keeps a foreign frame from driving
|
||||
// it; the height is clamped to a sane floor so a bad payload can't collapse the player away.
|
||||
private const string ResizeScript =
|
||||
"""<script>window.addEventListener("message",function(e){var d=e.data;if(!d||d.type!=="deepdrft-embed-resize")return;var f=document.getElementById("deepdrft-embed");var h=Number(d.height);if(f&&h>=150)f.style.height=h+"px";});</script>""";
|
||||
// Host-side listener: resize the matching iframe when the embedded player posts its panel height.
|
||||
// The embedId field in the payload is matched against the snippet's own token so only this
|
||||
// iframe is driven — foreign frames or other release embeds on the same page cannot interfere.
|
||||
// The height is clamped to a sane floor so a bad payload can't collapse the player away.
|
||||
// Messages without embedId (older snippets) are silently ignored.
|
||||
private static string ResizeScript(string iframeId, string token) =>
|
||||
"<script>(function(){var id=\"" + iframeId + "\",tok=\"" + token + "\";" +
|
||||
"window.addEventListener(\"message\",function(e){var d=e.data;" +
|
||||
"if(!d||d.type!==\"deepdrft-embed-resize\"||d.embedId!==tok)return;" +
|
||||
"var f=document.getElementById(id);var h=Number(d.height);" +
|
||||
"if(f&&h>=150)f.style.height=h+\"px\";});})();</script>";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user