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.
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.
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.
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.
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.
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.
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.
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:
TAB_open [<id>, <url>, true, "", false, true]
-- last argument is defer_initial_nav.download_requested and
download_status_updated ... "finished" on that new tab's
source id, within ~200ms of TAB_open.allow-tab-open arriving after those, on the
opener tab -- the client tab did not exist yet.client_loc anywhere in the log.dl_tc_ui_finished from the client, so the
pending_close_during_download_ path
(safeview.cc:4525) never releases.TabClose. What appears instead is
tab_close <id> travelling the other way --
a TAB_RPC_RENDERER_PUSH (type 634) on the
opener's tab_id, from the poll loop at
tab.js:531-549 noticing window.closed, and
answered by
SURROGATE_SERVER_SEND_CLIENT_MESSAGE reason="OnRPCTabClose".
TAB_ALIVE END lands in the same millisecond. Grep for
tab_close, not TAB_close -- the wire name is
lowercase and the opcode name is not what is on the wire.
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.