Skip to content

chore(bidi): add support for browser.setDownloadBehavior#39311

Open
hbenl wants to merge 1 commit intomicrosoft:mainfrom
hbenl:setDownloadBehavior
Open

chore(bidi): add support for browser.setDownloadBehavior#39311
hbenl wants to merge 1 commit intomicrosoft:mainfrom
hbenl:setDownloadBehavior

Conversation

@hbenl
Copy link
Collaborator

@hbenl hbenl commented Feb 18, 2026

Fixes #39305 and the following tests in Firefox:

  • library/download.spec.ts:
    • "download event > should report download when navigation turns into download"
    • "download event > should work with Cross-Origin-Opener-Policy"
    • "download event > should report downloads with acceptDownloads: false"
    • "download event > should report downloads with acceptDownloads: true"
    • "download event > should report downloads for download attribute"
    • "download event > should save to user-specified path without updating original path"
    • "download event > should save to two different paths with multiple saveAs calls"
    • "download event > should save to overwritten filepath"
    • "download event > should create subdirectories when saving to non-existent user-specified path"
    • "download event > should report non-navigation downloads"
    • "download event > should report download path within page.on('download', …) handler for Files"
    • "download event > should delete file"
    • "download event > should expose stream"
    • "download event > should delete downloads on context destruction"
    • "download event > should delete downloads on browser gone"
    • "download event > should download large binary.zip"
    • "download event > should not fail explicitly to cancel a download even if that is already finished"
    • "download event > should report downloads with interception"
    • "download event > should emit download event from nested iframes"
    • "should be able to download a PDF file"
    • "should be able to download a inline PDF file via response interception"
    • "should save to user-specified path"
    • "should download successfully when routing"
  • library/downloads-path.spec.ts:
    • "downloads path > should keep downloadsPath folder"
    • "downloads path > should delete downloads when context closes"
    • "downloads path > should accept downloads in persistent context"
    • "downloads path > should delete downloads when persistent context closes"
  • library/defaultbrowsercontext-1.spec.ts:
    • "should support acceptDownloads option"

@github-actions

This comment has been minimized.

@hbenl hbenl force-pushed the setDownloadBehavior branch from 1403bb3 to 795cd70 Compare February 18, 2026 15:33
@github-actions

This comment has been minimized.

@hbenl hbenl force-pushed the setDownloadBehavior branch from 795cd70 to 9ffca5d Compare February 18, 2026 16:22
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@hbenl
Copy link
Collaborator Author

hbenl commented Feb 18, 2026

Note that I added the test "should throw if browser dies" to the expectations file because of an issue with the current implementation of browser.setDownloadBehavior in Firefox, see https://bugzilla.mozilla.org/show_bug.cgi?id=2017252#c1.

@github-actions

This comment has been minimized.

return;

this._browserContext._browser._downloadCreated(originPage, event.navigation, event.url, event.suggestedFilename);
this._browserContext._browser._downloadCreated(originPage, event.navigation, event.url, event.suggestedFilename, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is Bidi different here? If event.navigation is not unique, maybe we can just combine it with with even.timestamp to produce a UUID or have a mapping in the Bidi client Download->UUID ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

event.navigation is unique and is still being used to identify the download.
The difference with Bidi is that the browsers use event.suggestedFilename as the filename for writing the download to disk (whereas with other protocols they use the ID that is passed to _downloadCreated() as the filename).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does it work if the user has two downloads with the same suggestedFilename, e.g. the user clicks twice on a link with download="foo.zip" attribute? If Firefox already modifies the suggested file name and guarantees its uniqueness, we can probably use it as the uuid or in that case we still need to change the logic of the download to use a different id for canceling download? Is there a plan to change the behavior to save the downloads with a guid file name and returning unmodified suggested file name in Bidi?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g. the user clicks twice on a link with download="foo.zip" attribute

In that case the second download would get foo(1).zip as the suggestedFilename. So suggestedFilename is unique in the download folder at the time when the download is started but if a download gets cancelled and then another one started, they could get the same suggestedFilename.

If Firefox already modifies the suggested file name and guarantees its uniqueness, we can probably use it as the uuid or in that case we still need to change the logic of the download to use a different id for canceling download?

Cancelling downloads hasn't been added to the specification yet (w3c/webdriver-bidi#1031) but I don't expect it to use suggestedFilename to identify a download.

Is there a plan to change the behavior to save the downloads with a guid file name and returning unmodified suggested file name in Bidi?

No.

constructor(page: Page, downloadsPath: string, uuid: string, url: string, suggestedFilename?: string, useSuggestedFilename?: boolean) {
const unaccessibleErrorMessage = page.browserContext._options.acceptDownloads === 'deny' ? 'Pass { acceptDownloads: true } when you are creating your browser context.' : undefined;
this.artifact = new Artifact(page, path.join(downloadsPath, uuid), unaccessibleErrorMessage, () => {
const downloadPath = path.join(downloadsPath, useSuggestedFilename ? suggestedFilename! : uuid);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use downloadFilename instead of useSuggestedFilename and avoid the variable with !:

const downloadPath = path.join(downloadsPath, downloadFilename ?? uuid);

@hbenl hbenl force-pushed the setDownloadBehavior branch from 9ffca5d to 25d3ad3 Compare February 27, 2026 08:45
@github-actions
Copy link
Contributor

Test results for "tests 1"

2 failed
❌ [webkit-library] › library/download.spec.ts:399 › download event › should save downloads to artifactsDir @webkit-ubuntu-22.04-node20
❌ [playwright-test] › expect.spec.ts:603 › should print expected/received before timeout @macos-latest-node20

8 flaky ⚠️ [chromium-library] › library/browser.spec.ts:24 › should create new page @smoke `@ubuntu-22.04-chromium-tip-of-tree`
⚠️ [chromium-library] › library/browser.spec.ts:24 › should create new page @smoke `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/browser.spec.ts:24 › should create new page @smoke `@chromium-ubuntu-22.04-node24`
⚠️ [chromium-library] › library/browser.spec.ts:24 › should create new page @smoke `@chromium-ubuntu-22.04-node20`
⚠️ [chromium-library] › library/browser.spec.ts:24 › should create new page @smoke `@chromium-ubuntu-22.04-node22`
⚠️ [firefox-library] › library/browser.spec.ts:24 › should create new page @smoke `@firefox-ubuntu-22.04-node20`
⚠️ [firefox-library] › library/inspector/cli-codegen-1.spec.ts:1080 › cli codegen › should not throw csp directive violation errors `@firefox-ubuntu-22.04-node20`
⚠️ [webkit-library] › library/browser.spec.ts:24 › should create new page @smoke `@webkit-ubuntu-22.04-node20`

38631 passed, 843 skipped


Merge workflow run.

@github-actions
Copy link
Contributor

Test results for "MCP"

12 failed
❌ [chrome] › mcp/init-page.spec.ts:21 › --init-page @mcp-windows-latest
❌ [chrome] › mcp/init-page.spec.ts:39 › --init-page w/ --init-script @mcp-windows-latest
❌ [chrome] › mcp/tracing.spec.ts:21 › check that trace is saved with --save-trace @mcp-windows-latest
❌ [chromium] › mcp/init-page.spec.ts:21 › --init-page @mcp-windows-latest
❌ [chromium] › mcp/init-page.spec.ts:39 › --init-page w/ --init-script @mcp-windows-latest
❌ [firefox] › mcp/init-page.spec.ts:21 › --init-page @mcp-windows-latest
❌ [firefox] › mcp/init-page.spec.ts:39 › --init-page w/ --init-script @mcp-windows-latest
❌ [webkit] › mcp/init-page.spec.ts:21 › --init-page @mcp-windows-latest
❌ [webkit] › mcp/init-page.spec.ts:39 › --init-page w/ --init-script @mcp-windows-latest
❌ [msedge] › mcp/init-page.spec.ts:21 › --init-page @mcp-windows-latest
❌ [msedge] › mcp/init-page.spec.ts:39 › --init-page w/ --init-script @mcp-windows-latest
❌ [firefox] › mcp/http.spec.ts:199 › http transport browser lifecycle (persistent) @mcp-macos-15

5121 passed, 171 skipped


Merge workflow run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Implement overriding download behavior for WebDriver BiDi

2 participants