Attachment download reached through a new tab

Reproduces the SGH ED dashboard failure: the user clicks to export a CSV, a new tab opens, and it just sits there blank. No file arrives and the file-scanning backend never sees a request.

The download itself is not the problem. In the field net-log the surrogate fetched the whole file (download_status_updated ... "finished", 94617/94617 bytes) on every attempt. What fails is delivery.

The surrogate routes download messages to the download item's own WebContents (safeview_download_manager_delegate.cc:525, then Safeview::GetSafeviewForDownloadItem), so they go out on the new tab's tab_id channel. There is no opener fallback on the download path -- client_loc is the only opcode that gets retargeted to the opener (safeview.cc:7696, SV-27932). But when TAB_open carried defer_initial_nav=true, the client opened that tab as a bare about:blank with no thin client in it, so nothing is listening. onDownloadRequested never runs, so registerNewDownload never runs, so onDownloadStatusUpdated returns early on its if (!dl_prog) guard and startFileProcessing is never called -- nothing is ever requested from /safeview-fileserv/.

The blank tab is never released either, and that part is an ordering bug: active_tab_open_cmd_.reset() at safeview.cc:7415 runs before the download early-return at :7418, so client_initial_location_deferred() flips false and the client_loc/Initial that would have navigated the client tab is never sent.

All cases below download the same results_<timestamp>.csv from attachment_csv.php: text/csv, Content-Disposition: attachment, 94617 bytes, matching the production response.

1. window.open() outside user activation (the reported case)

Deferring to a timer drops the transient activation, so the surrogate reports is_popup=true and the client takes the popup-modal route -- exactly what the capture shows (allow-tab-open(allow=true, prompted=true, 14)). The time the user spends on that modal is what put the client tab 1.3 seconds behind the download_requested that was addressed to it.

Expected failure: popup modal, then a tab that stays blank, no file, and no request to /safeview-fileserv/. Nothing reaps that tab from the surrogate side while you leave it open -- in the field capture it was closed on the client, and it was the opener's tab_close report that tore down the surrogate tab.

2. window.open() inside user activation

Same call, but straight from the click, so activation is live and the popup modal is skipped. Use this to separate the two contributing factors. The modal only widens the race; the deferred tab still never loads a thin client, so this is expected to fail too -- just without the modal. If this one works and case 1 does not, the problem is purely the modal delay; if both fail, it is the deferred tab itself.

3. Anchor with target="_blank" (comparison)

attachment_csv.php in a new tab

Goes through tabPreOpen rather than the popup modal, so the client tab exists before the surrogate navigates. Tells you whether the pre-open path is also affected.

4. Same-tab download (control)

attachment_csv.php in this tab

Expected to work, before and after any fix. This tab has a live thin client, so the download opcodes land on a channel that is listening.

5. Fetch, then open (closest to the real dashboard)

A dashboard typically builds the export server-side and only then opens the result, which is what puts the window.open outside the activation window in production. Behaviourally this is case 1; it is here because it is the shape a customer will actually recognise.

6. Slow body (activation expires mid-download)

Headers go out immediately so the download is detected at once, but the body is stretched past the 5s activation window. Separates this bug from the activation-expiry path in downloadWindowOpen (SV-31835), which fails differently -- there the file is scanned and only the final window.open is blocked.

What to look for

Enable "Auto-open DevTools for popups" and "Preserve log" first, or the blank tab takes its console with it.

Client: in the opener tab's console the download is registered only if you see tc-download-requested. Its absence is the failure. Also check the blank tab's URL -- if it is still about:blank then no client_loc ever arrived.

Network: a working download issues an XHR to /safeview-fileserv/ (status poll) and finally hits /safeview-fileserv/tc_download/<key>/. Neither appears when this reproduces, which is why the backend logs show nothing.

Surrogate net-log (chrome://net-export inside the surrogate), the signature from the field capture:

Case 1 only reproduces when defer_initial_nav comes back true, which needs one of two things (safeview.cc:3251): either defer_new_tab_nav set on the target URL's site config (default false), or the surrogate having latched has_seen_sticky_policy_, which makes use_surrogate_led_new_tab() defer every subsequent new-tab nav regardless of the flag. The latch is the easier way to arm this and is the more likely production trigger. If every case downloads normally, check TAB_open's last argument first -- the bug cannot show until it is true.