Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions docs/ceilings.md
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,12 @@ work when nobody knows it and that the call site never shows. The mechanism and
sibling covers keeps its pin. Notes not sent yet
live in the window: closing it, or the browser, loses them.

- **On macOS, a JavaScript dialog a page opens before its first paint leaves the pane black behind the dialog's
card** (`internal/browser/chrome_view.go`): headless Chrome there paints a page some time after its load, and
a page held by a dialog cannot paint, so a screencast started then has no frame to send until the dialog is
answered (Chrome 155 on the macos-latest runner, measured). A dialog opened once the page has been drawn, as
one an agent's click opens, shows the page behind it. Linux and Windows paint before the load returns.

- **A session browser's downloads go straight to the user's Downloads folder** (`internal/browser/downloads.go`,
`session_downloads.go`, `docs/browser-tab.md`): `XDG_DOWNLOAD_DIR` on Linux, `~/Downloads` on macOS and Windows,
even for a Windows user who moved that known folder. Chrome writes each one under its download id into a staging
Expand Down
11 changes: 11 additions & 0 deletions internal/browser/dialogs_live_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"testing"
"time"

"github.com/chromedp/cdproto/page"
"github.com/chromedp/chromedp"
"github.com/lichdotdev/lich/api"
"github.com/lichdotdev/lich/internal/chromium"
Expand Down Expand Up @@ -105,6 +106,16 @@ func TestChromeAPaneOpenedOnADialogShowsThePage(t *testing.T) {
if err := p.Navigate(ctx, srv.URL); err != nil {
t.Fatal(err)
}
// The page is drawn once first, as a page the agent clicked on was:
// headless Chrome on macOS has not painted it when Navigate returns, and a
// dialog held open before its first paint leaves no frame to cast
// (Chrome 155, macos-latest runner, measured 2026-10-28).
if err := p.runFree(ctx, chromedp.ActionFunc(func(ctx context.Context) error {
_, err := page.CaptureScreenshot().Do(ctx)
return err
})); err != nil {
t.Fatal(err)
}
if err := p.runFree(ctx, chromedp.Evaluate(`setTimeout(() => confirm('Delete?'), 0)`, nil)); err != nil {
t.Fatal(err)
}
Expand Down
Loading