Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions apps/desktop/src/preview/CdpRelay.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ describe("CDP relay extra sessions", () => {
});

describe("CDP relay downloads", () => {
it("applies the server's download directory and reports downloads on the root session", async () => {
it("captures preview downloads without changing the default browser context", async () => {
const send = vi.fn(async () => ({}));
const directories: Array<string | null> = [];
const written: Array<Record<string, unknown>> = [];
Expand All @@ -201,15 +201,59 @@ describe("CDP relay downloads", () => {
);
await settle();
expect(directories).toEqual(["/srv/artifacts"]);
expect(send).toHaveBeenCalledWith(
"Browser.setDownloadBehavior",
{ behavior: "allowAndName", downloadPath: "/srv/artifacts", eventsEnabled: true },
undefined,
);
expect(send.mock.calls).toEqual([
["Page.setDownloadBehavior", { behavior: "default" }, undefined],
]);
written.length = 0;
relay.event("Browser.downloadWillBegin", { guid: "g1", suggestedFilename: "r.csv" }, "");
relay.event("Page.downloadWillBegin", { guid: "g1", suggestedFilename: "r.csv" }, "");
relay.event("Page.downloadProgress", { guid: "g1", state: "completed" }, "");
expect(written).toEqual([
{ method: "Browser.downloadWillBegin", params: { guid: "g1", suggestedFilename: "r.csv" } },
{ method: "Browser.downloadProgress", params: { guid: "g1", state: "completed" } },
]);
});

it("keeps denial scoped to the preview and restores Electron's save handling when allowed", async () => {
const send = vi.fn(async () => ({}));
const directories: Array<string | null> = [];
const relay = createCdpRelayConnection(
makeTarget(send, (directory) => directories.push(directory)),
() => {},
);
for (const [id, behavior] of ["deny", "allowAndName"].entries()) {
relay.receive(
JSON.stringify({
id,
method: "Browser.setDownloadBehavior",
params: { behavior, downloadPath: "/srv/artifacts" },
}),
);
await settle();
}
expect(directories).toEqual([null, "/srv/artifacts"]);
expect(send.mock.calls).toEqual([
["Page.setDownloadBehavior", { behavior: "deny" }, undefined],
["Page.setDownloadBehavior", { behavior: "default" }, undefined],
]);
});

it("does not publish download events when the connection has disabled them", async () => {
const written: Array<Record<string, unknown>> = [];
const relay = createCdpRelayConnection(makeTarget(vi.fn(async () => ({}))), (raw) =>
written.push(JSON.parse(raw)),
);
relay.receive(JSON.stringify({ id: 1, method: "Target.setAutoAttach", params: {} }));
relay.receive(
JSON.stringify({
id: 2,
method: "Browser.setDownloadBehavior",
params: { behavior: "allowAndName", downloadPath: "/srv/artifacts", eventsEnabled: false },
}),
);
await settle();
written.length = 0;
relay.event("Page.downloadWillBegin", { guid: "g1" }, "");
relay.event("Page.downloadProgress", { guid: "g1", state: "completed" }, "");
expect(written).toEqual([]);
});
});
13 changes: 10 additions & 3 deletions apps/desktop/src/preview/CdpRelay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export function createCdpRelayConnection(
): CdpRelayConnection {
const send = (message: Record<string, unknown>) => write(JSON.stringify(message));
let attached = false;
let downloadEventsEnabled = false;
/** Relay-created page sessions share one real debugger; child frame sessions retain their own ids. */
const sessions = new Map<string, "browser" | "page">([[PAGE_SESSION_ID, "page"]]);
let sessionSequence = 0;
Expand All @@ -78,8 +79,13 @@ export function createCdpRelayConnection(
const directory = command.params?.["downloadPath"];
const allowed = command.params?.["behavior"] !== "deny" && typeof directory === "string";
target.setDownloadDirectory(allowed ? directory : null);
const { browserContextId: _ignored, ...params } = command.params ?? {};
return target.send("Browser.setDownloadBehavior", params, undefined);
downloadEventsEnabled = command.params?.["eventsEnabled"] === true;
// Browser-scoped behavior targets Electron's app session; preview paths belong to will-download.
return target.send(
"Page.setDownloadBehavior",
{ behavior: command.params?.["behavior"] === "deny" ? "deny" : "default" },
undefined,
);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
}
case "Browser.getVersion":
return {
Expand Down Expand Up @@ -186,9 +192,10 @@ export function createCdpRelayConnection(
},
event: (method, params, sessionId) => {
if (!attached) return;
if (method.startsWith("Page.download")) method = method.replace("Page.", "Browser.");
// Download events are the browser's; Playwright listens on its root session.
if (method.startsWith("Browser.download")) {
send({ method, params });
if (downloadEventsEnabled) send({ method, params });
return;
}
// Electron reports the page's own events with an empty session id.
Expand Down
4 changes: 3 additions & 1 deletion apps/desktop/src/preview/DesktopBrowserHost.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -934,9 +934,11 @@ describe("DesktopBrowserHost", () => {
}),
}),
);
debuggee.emit("Browser.downloadWillBegin", { guid: "guid-1", suggestedFilename: "r.csv" });
debuggee.emit("Page.downloadWillBegin", { guid: "guid-1", suggestedFilename: "r.csv" });
expect(host.placeDownload(makeDebuggee().tab.webContents, item)).toBe(false);
expect(host.placeDownload(debuggee.tab.webContents, item)).toBe(true);
expect(paths).toEqual(["/srv/downloads/guid-1"]);
expect(host.placeDownload(debuggee.tab.webContents, item)).toBe(false);
}),
);

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/preview/DesktopBrowserHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ export const make = Effect.gen(function* () {
focusReleasing: false,
screencasts: new Set(),
onMessage: (_event, method, params, sessionId) => {
if (method === "Browser.downloadWillBegin") {
if (method === "Page.downloadWillBegin") {
const guid = (params as { guid?: unknown } | undefined)?.guid;
tab.pendingDownloadGuid = typeof guid === "string" ? guid : null;
}
Expand Down
Loading