Skip to content

fix(browser): open the file chooser for a file input, and land a Leave on a busy machine - #993

Merged
omartelo merged 1 commit into
mainfrom
fix/browser-file-chooser
Oct 30, 2026
Merged

omartelo merged 1 commit into
mainfrom
fix/browser-file-chooser

Conversation

@omartelo

Copy link
Copy Markdown
Collaborator

File inputs

A headless Chrome has no file chooser, so a click on a file input in the session browser did nothing (a profile picture upload, for one). Each tab now intercepts the chooser (Page.setInterceptFileChooserDialog), and Page.fileChooserOpened opens the system chooser the attach button uses, through project.ZenityPicker: PickFile for a single input, the new PickFiles for one with multiple. The picked paths fill the input with DOM.setFileInputFiles; Cancel leaves it as it was.

The chooser opens only while a pane shows the page (or in a headed window): an agent's click on a file input in a page nobody is looking at leaves it empty, and no tool fills one. The input's accept filter is not passed on. Both are in docs/ceilings.md.

Leave on a busy machine

TestChromeADialogWaitsForTheAgentsAnswer/beforeunload failed 6 in 10 under the gate's load. Root cause, measured on Chromium 155: a beforeunload accepted too soon after it opens has Chrome hold the navigation's request (it never reaches the server), cancel it with ERR_ABORTED and reload the page, sometimes asking again. How soon is too soon grows with load: about 450 ms idle, 2 to 3 s with Chromium held to 30% of a core. It is not lich's doing (a raw Page.navigate with no cancellation and no reads after the accept does the same), and no CDP event marks the moment, so the fixed beforeunloadSettle cannot cover it.

A leave now recovers instead (chrome_leave.go): the URL a beforeunload holds is kept from the navigation that started just before it; after an accept, a reload on that tab counts as an abort, its own beforeunload is accepted unseen (the person already chose Leave), and once it lands the held URL is loaded again, up to three times. Settle waits for the leave to land, up to 15 s, so the agent's answer is the page it left for.

Test plan

  • files_live_test.go: a single and a multiple file input in real Chromium fill with the picked files; fails without the interception
  • files_test.go: picker per mode, cancel, error, no pane
  • chrome_leave_test.go: a leave lands, an aborted one is taken up until its tries run out, dismiss and alerts do not leave (-race)
  • TestChromeADialogWaitsForTheAgentsAnswer with the test's CPU held by CPUQuota: 6/10 failed at 30% before, 0/20 at 30% and 0/20 at 20% after
  • gofmt, go vet ./..., go test ./... in the gate's memory jail; GOOS=darwin|windows go build

…e on a busy machine

A headless Chrome has no file chooser, so a click on a file input in the
session browser did nothing. The page now intercepts the chooser and opens
the system one the attach button uses, for one file or several as the input
asks, while a pane shows the page.

A beforeunload accepted too soon has Chrome abort the navigation it held and
reload the page, and how soon is too soon grows with load (about 450 ms idle,
2 to 3 s with Chromium held to 30% of a core), which made
TestChromeADialogWaitsForTheAgentsAnswer fail 6 in 10 under the gate's load.
A leave now watches for that reload and takes the held navigation up again
once it lands.
@omartelo
omartelo merged commit eae230c into main Oct 30, 2026
7 checks passed
@omartelo
omartelo deleted the fix/browser-file-chooser branch October 30, 2026 14:49
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.

1 participant