Reproduces the Ivalua / Docebo SaaS training-materials failure: the user clicks
Download on ivalua.docebosaas.com, a new blank tab opens,
and halfway through the download (~5-6 seconds) the tab closes on its own and the
download is terminated without saving the file.
cdn2.dcbstatic.com/6650.9ee50783aa52ce2a.js
opens an about:blank popup window, fetches metadata via XHR (~350ms),
navigates the popup to the download redirect URL, and sets a hardcoded 5000 ms timer:
setTimeout(() => Ie?.close(), 5e3).
win.closed and sends tab_close
to the surrogate. The surrogate executes view->SetForceCloseDuringDownload(true) and destroys
the child tab WebContents, immediately aborting the in-flight download before file transfer and scanning can finish.
win.close().
Without win.close(), the tab stayed open indefinitely and the download succeeded every time.
From native capture ivalua.docebosaas.com_mac_native.har entry 216
(script https://cdn2.dcbstatic.com/6650.9ee50783aa52ce2a.js):
download(Ee) {
const ye = {file_id: Ee.id, course_id: this.course_id},
Ie = window.open(); // opens about:blank
new Promise((de, Pe) => {
this.backendService.request("/learn/v1/filerepo/getCourseFile", "GET", ye).subscribe(we => {
if (we) {
const it = we.data.Files;
if (10 !== it.item_type)
if (0 === it.item_type)
Ie.location.href = it.path;
else {
let ot = `${window.location.origin}/learn/v1/filerepo/downloadCourseFile?course_id=${this.course_id}&file_id=${it.id_file}`;
this.accessTokenInCookieEnabled || (ot += `&access_token=${(0,_e.iD)()}`);
Ie.location.href = ot;
const At = this;
// *** CRITICAL: Application explicitly closes popup after 5000 ms! ***
setTimeout(() => {
!At.browserDetect.isIE() && !At.browserDetect.isMobile() && !At.browserDetect.isIPad() && Ie?.close();
}, 5e3);
}
de({type: "success", message: _.y.t("standard", "Upload success")});
}
});
});
}
| Behavior | Evidence in Logs & Codebase |
|---|---|
| Application schedules window closure at 5 seconds | setTimeout(() => Ie?.close(), 5e3) in Docebo Angular bundle. 356ms XHR + 5000ms = 5356ms. |
Thin Client sends tab_close at ~6.0s |
ivalua.docebosaas.com_.har: allow-tab-open sent at t=1783586019.46s; ["tab_close", 5] sent at t=1783586025.47s (delta = 6.01s). |
| Thin Client tab close poller | service/src/thin-client/tab.js:531-549: setInterval(..., 400) checks win.closed and sends ['tab_close', tab_id]. |
| Surrogate forces immediate close, killing download | chromium/src/safeview/browser/safeview_surrogate_server.cc:1433:
view->SetForceCloseDuringDownload(true) overrides download delay in Safeview::CloseContents and kills the WebContents. |
| Download fails "halfway through" | Surrogate-to-client progress is scaled 0.0-0.5 during download from S3, reaching 50% when surrogate download completes. At ~5s, surrogate is downloading/scanning, and closing the tab destroys the transfer. |
ms from navigation (Docebo SaaS hardcodes 5000 ms. Uncheck or set to 0 to disable close)
Size MB transfer duration ms file type
Exact production sequence: window.open('') during click → 356 ms metadata XHR
→ set location to 2-redirect chain ending on 25MB archive → call win.close() after 5000 ms.
Expected failure in Menlo Isolation: The new tab opens, begins downloading/buffering,
and at ~5.7s (5000ms after navigation) the tab is closed by win.close(). The download is aborted halfway through,
reproducing the field issue.
Exact same blank tab, metadata XHR, and 2-redirect chain as Case 1, but win.close() is NOT called.
Expected pass: Without premature tab closure, the download completes fully,
proving that the 5-second win.close() is the direct cause of the failure.
Demonstrates the race against transfer duration. If the transfer duration is 7000ms, close timeouts shorter than 7000ms will fail, while close timeouts longer than 7000ms will succeed.
Direct window.open(url) with no blank tab and no close timer.
Expected pass.
Isolates cross-origin behavior.
Navigate current tab to the download URL.
Expected pass.