const SAVE_PER_SITE_PREF = "browser.download.lastDir.savePerSite"; function test_deleted_iframe(perSitePref, windowOptions = {}) { return async function () { await SpecialPowers.pushPrefEnv({ set: [[SAVE_PER_SITE_PREF, perSitePref]], }); let { DownloadLastDir } = ChromeUtils.importESModule( "resource://gre/modules/DownloadLastDir.sys.mjs" ); let win = await BrowserTestUtils.openNewBrowserWindow(windowOptions); let tab = await BrowserTestUtils.openNewForegroundTab( win.gBrowser, "about:mozilla" ); let doc = tab.linkedBrowser.contentDocument; let iframe = doc.createElement("iframe"); doc.body.appendChild(iframe); ok(iframe.contentWindow, "iframe should have a window"); let gDownloadLastDir = new DownloadLastDir(iframe.contentWindow); let cw = iframe.contentWindow; let promiseIframeWindowGone = new Promise((resolve, reject) => { Services.obs.addObserver(function obs(subject, topic) { if (subject == cw) { Services.obs.removeObserver(obs, topic); resolve(); } }, "dom-window-destroyed"); }); iframe.remove(); await promiseIframeWindowGone; cw = null; ok(!iframe.contentWindow, "Managed to destroy iframe"); let someDir = "blah"; try { someDir = await gDownloadLastDir.getFileAsync("http://www.mozilla.org/"); } catch (ex) { ok( false, "Got an exception trying to get the directory where things should be saved." ); console.error(ex); } // NB: someDir can legitimately be null here when set, hence the 'blah' workaround: isnot( someDir, "blah", "Should get a file even after the window was destroyed." ); try { gDownloadLastDir.setFile("http://www.mozilla.org/", null); } catch (ex) { ok( false, "Got an exception trying to set the directory where things should be saved." ); console.error(ex); } await BrowserTestUtils.closeWindow(win); }; } add_task(test_deleted_iframe(false)); add_task(test_deleted_iframe(false)); add_task(test_deleted_iframe(true, { private: true })); add_task(test_deleted_iframe(true, { private: true }));