diff --git a/src/main/browser/browser-manager-grab.test.ts b/src/main/browser/browser-manager-grab.test.ts index 43652e6b9db..5133aaed5b8 100644 --- a/src/main/browser/browser-manager-grab.test.ts +++ b/src/main/browser/browser-manager-grab.test.ts @@ -59,7 +59,8 @@ function makeGuest(id: number) { executeJavaScriptInIsolatedWorld: guestExecuteJavaScriptInIsolatedWorldMock, getZoomFactor: guestGetZoomFactorMock, capturePage: guestCapturePageMock, - getURL: vi.fn(() => 'https://example.com/') + getURL: vi.fn(() => 'https://example.com/'), + close: vi.fn() } as unknown as Electron.WebContents } diff --git a/src/main/browser/browser-manager.test.ts b/src/main/browser/browser-manager.test.ts index 286f172a645..492920686e8 100644 --- a/src/main/browser/browser-manager.test.ts +++ b/src/main/browser/browser-manager.test.ts @@ -1181,7 +1181,8 @@ describe('browserManager', () => { setWindowOpenHandler: guestSetWindowOpenHandlerMock, on: guestOnMock, off: guestOffMock, - openDevTools: guestOpenDevToolsMock + openDevTools: guestOpenDevToolsMock, + close: vi.fn() } webContentsFromIdMock.mockReturnValue(guest) @@ -1314,7 +1315,8 @@ describe('browserManager', () => { setWindowOpenHandler: guestSetWindowOpenHandlerMock, on: guestOnMock, off: guestOffMock, - openDevTools: guestOpenDevToolsMock + openDevTools: guestOpenDevToolsMock, + close: vi.fn() } webContentsFromIdMock.mockImplementation((id: number) => { if (id === guest.id) { @@ -2009,7 +2011,8 @@ describe('browserManager', () => { setWindowOpenHandler: guestSetWindowOpenHandlerMock, on: guestOnMock, off: guestOffMock, - openDevTools: guestOpenDevToolsMock + openDevTools: guestOpenDevToolsMock, + close: vi.fn() } const item = createDownloadItem() webContentsFromIdMock.mockImplementation((id: number) => { @@ -2032,6 +2035,7 @@ describe('browserManager', () => { browserManager.unregisterGuest('browser-1') + expect(guest.close).toHaveBeenCalledTimes(1) expect(item.cancel).toHaveBeenCalledTimes(1) expect(rendererSendMock).toHaveBeenCalledWith( 'browser:download-finished', @@ -2739,6 +2743,7 @@ describe('browserManager', () => { on: guestOnMock, off: guestOffMock, openDevTools: guestOpenDevToolsMock, + close: vi.fn(), getURL: vi.fn(() => 'https://example.com/'), debugger: { isAttached: vi.fn(() => false), diff --git a/src/main/browser/browser-manager.ts b/src/main/browser/browser-manager.ts index 6b51dc9a0dd..780b7aa0ab7 100644 --- a/src/main/browser/browser-manager.ts +++ b/src/main/browser/browser-manager.ts @@ -1073,6 +1073,14 @@ export class BrowserManager { const wcId = this.webContentsIdByTabId.get(browserTabId) if (wcId !== undefined) { this.tabIdByWebContentsId.delete(wcId) + // Why: webview.remove() in the renderer does not synchronously destroy + // the guest web contents — Chromium keeps its media session alive until + // GC, so media keys (F8 play/pause) still control a "dead" tab. + // Explicitly closing the web contents here tears it down immediately. + const wc = webContents.fromId(wcId) + if (wc && !wc.isDestroyed()) { + wc.close() + } } this.webContentsIdByTabId.delete(browserTabId) this.rendererWebContentsIdByTabId.delete(browserTabId)