1
0

feat: stream private office screens

This commit is contained in:
2026-08-11 21:31:15 -07:00
parent d841575315
commit 5ca214e4bb
28 changed files with 1754 additions and 35 deletions
+37 -1
View File
@@ -182,6 +182,7 @@ describe("remote office media presenter", () => {
/explicit opt-in/,
);
await media.startPresenter({ consent: { authorized: true, optedIn: true }, stream: stream as unknown as MediaStream, video: video as unknown as HTMLVideoElement });
assert.equal(media.state().status, "live", "an empty hosted room is ready for its first viewer");
await settle();
assert.equal(peers.length, 1);
assert.equal(peers[0]?.added[0], presenterTrack as unknown as MediaStreamTrack);
@@ -324,7 +325,7 @@ describe("remote office media viewer", () => {
});
const video = new FakeVideo();
await assert.rejects(media.startViewer({ decision: decision(false), video: video as unknown as HTMLVideoElement }), /ready live-stream/);
await media.startViewer({ decision: decision(), video: video as unknown as HTMLVideoElement });
await media.startViewer({ viewerOptIn: true, video: video as unknown as HTMLVideoElement });
await settle();
assert.equal(peers[0]?.transceivers[0], "video");
assert.deepEqual(peers[0]?.remote[0], { type: "offer", sdp: "presenter-offer" });
@@ -340,4 +341,39 @@ describe("remote office media viewer", () => {
assert.equal(video.srcObject, null);
assert.equal(media.state().status, "revoked");
});
it("forgets its grant when the server has already stopped the session", async () => {
const presenterPeer = { participantId: "presenter-opaque", role: "presenter" as const };
let emitEvent: (value: Uint8Array) => void = () => { throw new Error("event stream is not open"); };
let leaveCalls = 0;
const fetcher: typeof fetch = async (input, init = {}) => {
const body = JSON.parse(String(init.body)) as Record<string, unknown>;
if (String(input).endsWith("/join")) {
return Response.json(grant("screen-share-join-grant", String(body.requestId), "viewer", [presenterPeer]), { status: 201 });
}
if (String(input).endsWith("/events")) {
const stream = new ReadableStream<Uint8Array>({ start(controller) { emitEvent = (value) => controller.enqueue(value); } });
const resume = grant("screen-share-resume-grant", String(body.requestId), "viewer", [presenterPeer]);
emitEvent(new TextEncoder().encode(`data: ${JSON.stringify(resume)}\n\n`));
return new Response(stream, { status: 200, headers: { "Content-Type": "text/event-stream" } });
}
if (String(input).endsWith("/leave")) leaveCalls += 1;
return new Response(null, { status: 204 });
};
const media = createRemoteOfficeMedia({
role: "viewer", binding: BINDING, authenticatedFetch: fetcher, now: () => NOW,
peerConnectionFactory: () => new FakePeer() as unknown as RTCPeerConnection,
});
await media.startViewer({ viewerOptIn: true, video: new FakeVideo() as unknown as HTMLVideoElement });
await settle();
emitEvent(new TextEncoder().encode(`data: ${JSON.stringify({
type: "screen-share-stopped", protocolVersion: 1, sequence: 2, timestampMs: NOW + 1,
sessionId: "share-session", binding: BINDING, reason: "presenter-stopped",
})}\n\n`));
await settle();
assert.equal(media.state().status, "stopped");
assert.equal(media.state().sessionId, null);
await media.dispose();
assert.equal(leaveCalls, 0, "cleanup does not reuse a server-invalidated capability");
});
});