fix(call): send theme changes only once the call frame is ready (postMessage origin error)
CI / Build & Quality Checks (push) Skipped
CI / Secret scan (gitleaks) (push) Skipped
CI / Playwright smoke (e2e) (push) Skipped
CI / Build & Quality Checks (pull_request) Successful in 3m24s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 11s
CI / Playwright smoke (e2e) (pull_request) Successful in 18m12s
CI / Build & Quality Checks (push) Skipped
CI / Secret scan (gitleaks) (push) Skipped
CI / Playwright smoke (e2e) (push) Skipped
CI / Build & Quality Checks (pull_request) Successful in 3m24s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 11s
CI / Playwright smoke (e2e) (pull_request) Successful in 18m12s
Reported from the desktop app console on joining a call: "Failed to execute postMessage on DOMWindow: The target origin provided (http://127.0.0.1:44548) does not match the recipient window origin (http://localhost:44548)". useCallThemeSync calls embed.setTheme as soon as the call view mounts. With waitForIframeLoad: false that send goes out while the iframe is still on its initial about:blank, which has the app origin, so the browser refuses the message addressed to the call origin and the request hangs to a timeout. The theme was right anyway (it is in the frame URL), so this was noise plus a pending request. setTheme now only records the theme until the widget API is ready; on ready it sends the latest theme if it differs from the one the frame loaded with. Reproduced with the app on localhost and the call frame on 127.0.0.1 (as on desktop) against the local LiveKit stack: joining logged the error before, none after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
843a48dd10
commit
2612f71c57
@@ -133,6 +133,15 @@ export class CallEmbed {
|
||||
|
||||
private themeKind: ElementCallThemeKind = 'dark';
|
||||
|
||||
// The theme the frame was loaded with (its URL `theme` param), and whether
|
||||
// the widget API is ready. Until it is, the iframe may still be on its
|
||||
// initial about:blank (our own origin), so a send to the call's origin is
|
||||
// refused ("target origin … does not match the recipient window's origin")
|
||||
// and the request hangs to a timeout. Theme changes wait for ready.
|
||||
private loadedThemeKind: ElementCallThemeKind = 'dark';
|
||||
|
||||
private widgetReady = false;
|
||||
|
||||
// Watchdog: detects an iframe that never reaches a usable state.
|
||||
private loadWatchdog?: ReturnType<typeof setTimeout>;
|
||||
|
||||
@@ -360,6 +369,7 @@ export class CallEmbed {
|
||||
this.iframe = iframe;
|
||||
this.container = container;
|
||||
this.themeKind = themeKind;
|
||||
this.loadedThemeKind = themeKind;
|
||||
|
||||
const controlState = initialControlState ?? new CallControlState(true, false, true);
|
||||
this.control = new CallControl(controlState, call, iframe);
|
||||
@@ -375,6 +385,13 @@ export class CallEmbed {
|
||||
// happy path (onCallJoined) clears it too; these cover earlier signals so a
|
||||
// user sitting in the lobby/prescreen isn't flagged as an error.
|
||||
this.disposables.push(this.onReady(() => this.settleLoad()));
|
||||
this.disposables.push(
|
||||
this.onReady(() => {
|
||||
this.widgetReady = true;
|
||||
// A theme change made while the frame was loading.
|
||||
if (this.themeKind !== this.loadedThemeKind) this.sendTheme();
|
||||
}),
|
||||
);
|
||||
this.disposables.push(this.onCapabilitiesNotified(() => this.settleLoad()));
|
||||
this.disposables.push(this.onPreparingError(() => this.settleLoad('iframe')));
|
||||
|
||||
@@ -399,12 +416,18 @@ export class CallEmbed {
|
||||
return this.room.roomId;
|
||||
}
|
||||
|
||||
public setTheme(theme: ElementCallThemeKind) {
|
||||
public setTheme(theme: ElementCallThemeKind): Promise<unknown> {
|
||||
this.themeKind = theme;
|
||||
// Before ready, the URL theme applies and the change is sent on ready.
|
||||
if (!this.widgetReady) return Promise.resolve();
|
||||
return this.sendTheme();
|
||||
}
|
||||
|
||||
private sendTheme(): Promise<unknown> {
|
||||
return this.call.transport
|
||||
.send(WidgetApiToWidgetAction.ThemeChange, { name: theme })
|
||||
.send(WidgetApiToWidgetAction.ThemeChange, { name: this.themeKind })
|
||||
.catch(() => {
|
||||
// Widget transport not ready yet; theme URL param is the fallback
|
||||
// The frame went away mid-send; nothing to do.
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user