47 lines
2.0 KiB
TypeScript
47 lines
2.0 KiB
TypeScript
import { test } from 'node:test';
|
|||
|
|
import assert from 'node:assert/strict';
|
||
|
|
import { ClientWidgetApi } from 'matrix-widget-api';
|
||
|
|
import { isFromWidgetFrame, restrictWidgetMessages } from './widgetTransport';
|
||
|
|
|
||
|
|
const frame = {} as Window;
|
||
|
|
const other = {} as Window;
|
||
|
|
const ORIGIN = 'https://call.example.org';
|
||
|
|
|
||
|
|
test('isFromWidgetFrame: only the widget frame at its origin', () => {
|
||
|
|
assert.equal(isFromWidgetFrame({ source: frame, origin: ORIGIN }, frame, ORIGIN), true);
|
||
|
|
assert.equal(isFromWidgetFrame({ source: other, origin: ORIGIN }, frame, ORIGIN), false);
|
||
|
|
assert.equal(isFromWidgetFrame({ source: frame, origin: 'null' }, frame, ORIGIN), false);
|
||
|
|
assert.equal(
|
||
|
|
isFromWidgetFrame({ source: frame, origin: 'https://evil.example' }, frame, ORIGIN),
|
||
|
|
false,
|
||
|
|
);
|
||
|
|
assert.equal(isFromWidgetFrame({ source: null, origin: ORIGIN }, null, ORIGIN), false);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('restrictWidgetMessages swaps the listener and drops foreign messages', () => {
|
||
|
|
const seen: unknown[] = [];
|
||
|
|
const original = (ev: MessageEvent) => {
|
||
|
|
seen.push(ev.data);
|
||
|
|
};
|
||
|
|
const transport = { handleMessage: original };
|
||
|
|
const api = { transport } as unknown as ClientWidgetApi;
|
||
|
|
const iframe = { contentWindow: frame } as HTMLIFrameElement;
|
||
|
|
const listeners = new Set<EventListener>([original as EventListener]);
|
||
|
|
const inbound = {
|
||
|
|
addEventListener: (_t: string, l: EventListener) => listeners.add(l),
|
||
|
|
removeEventListener: (_t: string, l: EventListener) => listeners.delete(l),
|
||
|
|
} as unknown as Window;
|
||
|
|
|
||
|
|
restrictWidgetMessages(api, iframe, ORIGIN, inbound);
|
||
|
|
assert.equal(listeners.has(original as EventListener), false);
|
||
|
|
assert.equal(listeners.size, 1);
|
||
|
|
assert.equal(transport.handleMessage === original, false);
|
||
|
|
|
||
|
|
const dispatch = (ev: Partial<MessageEvent>) =>
|
||
|
|
listeners.forEach((l) => l(ev as unknown as Event));
|
||
|
|
dispatch({ source: other, origin: ORIGIN, data: 'spoof' });
|
||
|
|
dispatch({ source: frame, origin: 'null', data: 'wrong-origin' });
|
||
|
|
dispatch({ source: frame, origin: ORIGIN, data: 'real' });
|
||
|
|
assert.deepEqual(seen, ['real']);
|
||
|
|
});
|