Course file download through a blank new tab

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.

Root Cause Summary: Docebo SaaS client-side Angular code in 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).

In a native browser, the browser's download manager claims the attachment stream in the background, so closing the blank popup window at 5s does not interrupt the download.
In Menlo Isolation, Thin Client detects 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.

Why previous test scripts failed to reproduce: The previous test author assumed the child tab closed on its own and never called win.close(). Without win.close(), the tab stayed open indefinitely and the download succeeded every time.

What the application actually does

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")});
            }
        });
    });
}

Isolated HAR and Surrogate Code Analysis

BehaviorEvidence 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.

Controls and Settings

1. Window Close Settings (Docebo SaaS behavior)

ms from navigation (Docebo SaaS hardcodes 5000 ms. Uncheck or set to 0 to disable close)

2. Transfer Size and Duration

Size MB   transfer duration ms   file type  

3. Optional: Second host for cross-site hop

Test Cases

Case 1: The Reported Ivalua/Docebo Flow (Reproduction - Expected Failure)

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.

Case 2: Control -- Identical Flow WITHOUT win.close() (Expected Pass)

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.

Case 3: Close-Delay Sweep -- The Discriminator

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.

Case 4: Control -- Direct window.open(url) (Smoke Test)

Direct window.open(url) with no blank tab and no close timer.

Expected pass.

Case 5: Blank tab, Same-Origin vs Cross-Origin (No close vs With close)

Isolates cross-origin behavior.

Case 6: Same Tab -- Control

Navigate current tab to the download URL.

Expected pass.

Client-side Trace