From 59ebde4b42a2316794eea414605708ba57697d1e Mon Sep 17 00:00:00 2001 From: srogotzki Date: Tue, 5 Oct 2021 15:31:08 +0200 Subject: [PATCH 1/9] feat: Added ability to configure if window should close when opener closes --- lib/browser/api/web-contents.ts | 44 ++++++++++++++++++++--------- lib/browser/guest-window-manager.ts | 21 +++++++++----- typings/internal-electron.d.ts | 2 +- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/lib/browser/api/web-contents.ts b/lib/browser/api/web-contents.ts index 5705cec695a07..e9b614bbc0422 100644 --- a/lib/browser/api/web-contents.ts +++ b/lib/browser/api/web-contents.ts @@ -492,41 +492,51 @@ WebContents.prototype.loadURL = function (url, options) { return p; }; -WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => ({action: 'allow'} | {action: 'deny', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions})) { +WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => ({action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions, closeWithOpener?: boolean})) { this._windowOpenHandler = handler; }; -WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): BrowserWindowConstructorOptions | null { +WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): {browserWindowConstructorOptions: BrowserWindowConstructorOptions | null, closeWithOpener: boolean} { + const defaultResponse = { + browserWindowConstructorOptions: null, + closeWithOpener: true, + }; if (!this._windowOpenHandler) { - return null; + return defaultResponse; } const response = this._windowOpenHandler(details); if (typeof response !== 'object') { event.preventDefault(); console.error(`The window open handler response must be an object, but was instead of type '${typeof response}'.`); - return null; + return defaultResponse; } if (response === null) { event.preventDefault(); console.error('The window open handler response must be an object, but was instead null.'); - return null; + return defaultResponse; } if (response.action === 'deny') { event.preventDefault(); - return null; + return defaultResponse; } else if (response.action === 'allow') { if (typeof response.overrideBrowserWindowOptions === 'object' && response.overrideBrowserWindowOptions !== null) { - return response.overrideBrowserWindowOptions; + return { + browserWindowConstructorOptions: response.overrideBrowserWindowOptions, + closeWithOpener: typeof response.closeWithOpener === "boolean" ? response.closeWithOpener : true, + }; } else { - return {}; + return { + browserWindowConstructorOptions: {}, + closeWithOpener: typeof response.closeWithOpener === "boolean" ? response.closeWithOpener : true, + }; } } else { event.preventDefault(); console.error('The window open handler response must be an object with an \'action\' property of \'allow\' or \'deny\'.'); - return null; + return defaultResponse; } }; @@ -651,7 +661,8 @@ WebContents.prototype._init = function () { postBody, disposition }; - const options = this._callWindowOpenHandler(event, details); + const result = this._callWindowOpenHandler(event, details); + const options = result.browserWindowConstructorOptions; if (!event.defaultPrevented) { openGuestWindow({ event, @@ -660,12 +671,14 @@ WebContents.prototype._init = function () { referrer, postData, overrideBrowserWindowOptions: options || {}, - windowOpenArgs: details + windowOpenArgs: details, + closeWithOpener: result.closeWithOpener, }); } }); let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null; + let windowOpenCloseWithOpenerOption: boolean = true; this.on('-will-add-new-contents' as any, (event: ElectronInternal.Event, url: string, frameName: string, rawFeatures: string, disposition: Electron.HandlerDetails['disposition'], referrer: Electron.Referrer, postData: PostData) => { const postBody = postData ? { data: postData, @@ -679,7 +692,9 @@ WebContents.prototype._init = function () { referrer, postBody }; - windowOpenOverriddenOptions = this._callWindowOpenHandler(event, details); + const result = this._callWindowOpenHandler(event, details); + windowOpenCloseWithOpenerOption = result.closeWithOpener; + windowOpenOverriddenOptions = result.browserWindowConstructorOptions; if (!event.defaultPrevented) { const secureOverrideWebPreferences = windowOpenOverriddenOptions ? { // Allow setting of backgroundColor as a webPreference even though @@ -711,6 +726,8 @@ WebContents.prototype._init = function () { referrer: Electron.Referrer, rawFeatures: string, postData: PostData) => { const overriddenOptions = windowOpenOverriddenOptions || undefined; windowOpenOverriddenOptions = null; + // true is the default + windowOpenCloseWithOpenerOption = true; if ((disposition !== 'foreground-tab' && disposition !== 'new-window' && disposition !== 'background-tab')) { @@ -730,7 +747,8 @@ WebContents.prototype._init = function () { url, frameName, features: rawFeatures - } + }, + closeWithOpener: windowOpenCloseWithOpenerOption, }); }); } diff --git a/lib/browser/guest-window-manager.ts b/lib/browser/guest-window-manager.ts index 9815865f72499..039be7f74c307 100644 --- a/lib/browser/guest-window-manager.ts +++ b/lib/browser/guest-window-manager.ts @@ -29,7 +29,7 @@ const getGuestWindowByFrameName = (name: string) => frameNamesToWindow.get(name) * user to preventDefault() on the passed event (which ends up calling * DestroyWebContents). */ -export function openGuestWindow ({ event, embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs }: { +export function openGuestWindow ({ event, embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, closeWithOpener }: { event: { sender: WebContents, defaultPrevented: boolean }, embedder: WebContents, guest?: WebContents, @@ -38,6 +38,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition postData?: PostData, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions, windowOpenArgs: WindowOpenArgs, + closeWithOpener: boolean, }): BrowserWindow | undefined { const { url, frameName, features } = windowOpenArgs; const { options: browserWindowOptions } = makeBrowserWindowOptions({ @@ -77,7 +78,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition ...browserWindowOptions }); - handleWindowLifecycleEvents({ embedder, frameName, guest: window }); + handleWindowLifecycleEvents({ embedder, frameName, guest: window, closeWithOpener }); embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, referrer, postData }); @@ -90,10 +91,11 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition * too is the guest destroyed; this is Electron convention and isn't based in * browser behavior. */ -const handleWindowLifecycleEvents = function ({ embedder, guest, frameName }: { +const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, closeWithOpener }: { embedder: WebContents, guest: BrowserWindow, - frameName: string + frameName: string, + closeWithOpener: boolean }) { const closedByEmbedder = function () { guest.removeListener('closed', closedByUser); @@ -101,9 +103,13 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName }: { }; const closedByUser = function () { - embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder); + if (closeWithOpener) { + embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder); + } }; - embedder.once('current-render-view-deleted' as any, closedByEmbedder); + if (closeWithOpener) { + embedder.once('current-render-view-deleted' as any, closedByEmbedder); + } guest.once('closed', closedByUser); if (frameName) { @@ -163,7 +169,8 @@ function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs, handleWindowLifecycleEvents({ embedder: event.sender, guest: newGuest, - frameName + frameName, + closeWithOpener: true, }); } return true; diff --git a/typings/internal-electron.d.ts b/typings/internal-electron.d.ts index 666775c16a257..04159553aad5f 100644 --- a/typings/internal-electron.d.ts +++ b/typings/internal-electron.d.ts @@ -63,7 +63,7 @@ declare namespace Electron { equal(other: WebContents): boolean; browserWindowOptions: BrowserWindowConstructorOptions; _windowOpenHandler: ((details: Electron.HandlerDetails) => any) | null; - _callWindowOpenHandler(event: any, details: Electron.HandlerDetails): Electron.BrowserWindowConstructorOptions | null; + _callWindowOpenHandler(event: any, details: Electron.HandlerDetails): {browserWindowConstructorOptions: Electron.BrowserWindowConstructorOptions | null, closeWithOpener: boolean}; _setNextChildWebPreferences(prefs: Partial & Pick): void; _send(internal: boolean, channel: string, args: any): boolean; _sendToFrameInternal(frameId: number | [number, number], channel: string, ...args: any[]): boolean; From b4913df50625d688dbeb0be0c5bc2d97a3feb0b0 Mon Sep 17 00:00:00 2001 From: srogotzki Date: Wed, 6 Oct 2021 11:07:47 +0200 Subject: [PATCH 2/9] fix: check if embedder is destroyed --- lib/browser/guest-window-manager.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/browser/guest-window-manager.ts b/lib/browser/guest-window-manager.ts index 039be7f74c307..27b584f0ff6e7 100644 --- a/lib/browser/guest-window-manager.ts +++ b/lib/browser/guest-window-manager.ts @@ -103,8 +103,11 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, clos }; const closedByUser = function () { - if (closeWithOpener) { - embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder); + // Embedder might have been closed + if (!embedder.isDestroyed()) { + if (closeWithOpener) { + embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder); + } } }; if (closeWithOpener) { @@ -170,7 +173,7 @@ function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs, embedder: event.sender, guest: newGuest, frameName, - closeWithOpener: true, + closeWithOpener: true }); } return true; From 2fbadf6cb90fd9df221533cec4913ddab93d28f5 Mon Sep 17 00:00:00 2001 From: srogotzki Date: Thu, 7 Oct 2021 08:44:38 +0200 Subject: [PATCH 3/9] fix: correctly take over closeWithOpener property --- lib/browser/api/web-contents.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/browser/api/web-contents.ts b/lib/browser/api/web-contents.ts index e9b614bbc0422..c68d0252dc520 100644 --- a/lib/browser/api/web-contents.ts +++ b/lib/browser/api/web-contents.ts @@ -499,7 +499,7 @@ WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electr WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): {browserWindowConstructorOptions: BrowserWindowConstructorOptions | null, closeWithOpener: boolean} { const defaultResponse = { browserWindowConstructorOptions: null, - closeWithOpener: true, + closeWithOpener: true }; if (!this._windowOpenHandler) { return defaultResponse; @@ -525,12 +525,12 @@ WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, if (typeof response.overrideBrowserWindowOptions === 'object' && response.overrideBrowserWindowOptions !== null) { return { browserWindowConstructorOptions: response.overrideBrowserWindowOptions, - closeWithOpener: typeof response.closeWithOpener === "boolean" ? response.closeWithOpener : true, + closeWithOpener: typeof response.closeWithOpener === 'boolean' ? response.closeWithOpener : true }; } else { return { browserWindowConstructorOptions: {}, - closeWithOpener: typeof response.closeWithOpener === "boolean" ? response.closeWithOpener : true, + closeWithOpener: typeof response.closeWithOpener === 'boolean' ? response.closeWithOpener : true }; } } else { @@ -672,7 +672,7 @@ WebContents.prototype._init = function () { postData, overrideBrowserWindowOptions: options || {}, windowOpenArgs: details, - closeWithOpener: result.closeWithOpener, + closeWithOpener: result.closeWithOpener }); } }); @@ -725,6 +725,7 @@ WebContents.prototype._init = function () { _userGesture: boolean, _left: number, _top: number, _width: number, _height: number, url: string, frameName: string, referrer: Electron.Referrer, rawFeatures: string, postData: PostData) => { const overriddenOptions = windowOpenOverriddenOptions || undefined; + const closeWithOpener = windowOpenCloseWithOpenerOption; windowOpenOverriddenOptions = null; // true is the default windowOpenCloseWithOpenerOption = true; @@ -748,7 +749,7 @@ WebContents.prototype._init = function () { frameName, features: rawFeatures }, - closeWithOpener: windowOpenCloseWithOpenerOption, + closeWithOpener }); }); } From 2de6d70ff2354a8dce4c3f95bd15a52ddeb13317 Mon Sep 17 00:00:00 2001 From: srogotzki Date: Thu, 7 Oct 2021 09:20:22 +0200 Subject: [PATCH 4/9] chore: Added documentation --- docs/api/window-open.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/api/window-open.md b/docs/api/window-open.md index a2cb76a2a569e..c3e017a719802 100644 --- a/docs/api/window-open.md +++ b/docs/api/window-open.md @@ -73,6 +73,11 @@ creating the window. Note that this is more powerful than passing options through the feature string, as the renderer has more limited privileges in deciding security preferences than the main process. +Additionally to `{ action: 'allow', overrideBrowserWindowOptions: { ... } }`, +`closeWithOpener` can be passed like: `{ action: 'allow', closeWithOpener: false, +overrideBrowserWindowOptions: { ... } }`. If set to `false`, child windows will not +be closed when the opener window closes. The default value is `true`. + ### Native `Window` example ```javascript From d73176ffd15c4e3703960ef5158916d4d1c8050f Mon Sep 17 00:00:00 2001 From: t57ser Date: Fri, 29 Oct 2021 11:00:14 +0200 Subject: [PATCH 5/9] Update docs/api/window-open.md Co-authored-by: John Kleinschmidt --- docs/api/window-open.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/window-open.md b/docs/api/window-open.md index c3e017a719802..79a023a9158e7 100644 --- a/docs/api/window-open.md +++ b/docs/api/window-open.md @@ -73,7 +73,7 @@ creating the window. Note that this is more powerful than passing options through the feature string, as the renderer has more limited privileges in deciding security preferences than the main process. -Additionally to `{ action: 'allow', overrideBrowserWindowOptions: { ... } }`, +In addition to passing in `action` and `overrideBrowserWindowOptions`, `closeWithOpener` can be passed like: `{ action: 'allow', closeWithOpener: false, overrideBrowserWindowOptions: { ... } }`. If set to `false`, child windows will not be closed when the opener window closes. The default value is `true`. From fc21022feeeb1b5915744e510a8e8c4c86c211bf Mon Sep 17 00:00:00 2001 From: t57ser Date: Wed, 26 Jan 2022 09:14:22 +0100 Subject: [PATCH 6/9] chore: refactor Co-authored-by: Jeremy Rose --- lib/browser/guest-window-manager.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/browser/guest-window-manager.ts b/lib/browser/guest-window-manager.ts index 27b584f0ff6e7..6fad78ee6dc53 100644 --- a/lib/browser/guest-window-manager.ts +++ b/lib/browser/guest-window-manager.ts @@ -104,10 +104,8 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, clos const closedByUser = function () { // Embedder might have been closed - if (!embedder.isDestroyed()) { - if (closeWithOpener) { - embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder); - } + if (!embedder.isDestroyed() && closeWithOpener) { + embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder); } }; if (closeWithOpener) { From f2cd0967ef4c220a7de74156105d31e93d82ffe1 Mon Sep 17 00:00:00 2001 From: t57ser Date: Thu, 27 Jan 2022 08:48:09 +0100 Subject: [PATCH 7/9] chore: changed property name from `closeWithOpener` to `outlivesOpener` --- docs/api/window-open.md | 6 +++--- lib/browser/api/web-contents.ts | 24 ++++++++++++------------ lib/browser/guest-window-manager.ts | 16 ++++++++-------- typings/internal-electron.d.ts | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/api/window-open.md b/docs/api/window-open.md index 79a023a9158e7..1925a5d1e7e5d 100644 --- a/docs/api/window-open.md +++ b/docs/api/window-open.md @@ -74,9 +74,9 @@ through the feature string, as the renderer has more limited privileges in deciding security preferences than the main process. In addition to passing in `action` and `overrideBrowserWindowOptions`, -`closeWithOpener` can be passed like: `{ action: 'allow', closeWithOpener: false, -overrideBrowserWindowOptions: { ... } }`. If set to `false`, child windows will not -be closed when the opener window closes. The default value is `true`. +`outlivesOpener` can be passed like: `{ action: 'allow', outlivesOpener: true, +overrideBrowserWindowOptions: { ... } }`. If set to `true`, the newly created +window will not close when the opener window closes. The default value is `false`. ### Native `Window` example diff --git a/lib/browser/api/web-contents.ts b/lib/browser/api/web-contents.ts index c68d0252dc520..4e2cd4acbda74 100644 --- a/lib/browser/api/web-contents.ts +++ b/lib/browser/api/web-contents.ts @@ -492,14 +492,14 @@ WebContents.prototype.loadURL = function (url, options) { return p; }; -WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => ({action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions, closeWithOpener?: boolean})) { +WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => ({action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions, outlivesOpener?: boolean})) { this._windowOpenHandler = handler; }; -WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): {browserWindowConstructorOptions: BrowserWindowConstructorOptions | null, closeWithOpener: boolean} { +WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): {browserWindowConstructorOptions: BrowserWindowConstructorOptions | null, outlivesOpener: boolean} { const defaultResponse = { browserWindowConstructorOptions: null, - closeWithOpener: true + outlivesOpener: false }; if (!this._windowOpenHandler) { return defaultResponse; @@ -525,12 +525,12 @@ WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, if (typeof response.overrideBrowserWindowOptions === 'object' && response.overrideBrowserWindowOptions !== null) { return { browserWindowConstructorOptions: response.overrideBrowserWindowOptions, - closeWithOpener: typeof response.closeWithOpener === 'boolean' ? response.closeWithOpener : true + outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false }; } else { return { browserWindowConstructorOptions: {}, - closeWithOpener: typeof response.closeWithOpener === 'boolean' ? response.closeWithOpener : true + outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false }; } } else { @@ -672,13 +672,13 @@ WebContents.prototype._init = function () { postData, overrideBrowserWindowOptions: options || {}, windowOpenArgs: details, - closeWithOpener: result.closeWithOpener + outlivesOpener: result.outlivesOpener }); } }); let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null; - let windowOpenCloseWithOpenerOption: boolean = true; + let windowOpenOutlivesOpenerOption: boolean = false; this.on('-will-add-new-contents' as any, (event: ElectronInternal.Event, url: string, frameName: string, rawFeatures: string, disposition: Electron.HandlerDetails['disposition'], referrer: Electron.Referrer, postData: PostData) => { const postBody = postData ? { data: postData, @@ -693,7 +693,7 @@ WebContents.prototype._init = function () { postBody }; const result = this._callWindowOpenHandler(event, details); - windowOpenCloseWithOpenerOption = result.closeWithOpener; + windowOpenOutlivesOpenerOption = result.outlivesOpener; windowOpenOverriddenOptions = result.browserWindowConstructorOptions; if (!event.defaultPrevented) { const secureOverrideWebPreferences = windowOpenOverriddenOptions ? { @@ -725,10 +725,10 @@ WebContents.prototype._init = function () { _userGesture: boolean, _left: number, _top: number, _width: number, _height: number, url: string, frameName: string, referrer: Electron.Referrer, rawFeatures: string, postData: PostData) => { const overriddenOptions = windowOpenOverriddenOptions || undefined; - const closeWithOpener = windowOpenCloseWithOpenerOption; + const outlivesOpener = windowOpenOutlivesOpenerOption; windowOpenOverriddenOptions = null; - // true is the default - windowOpenCloseWithOpenerOption = true; + // false is the default + windowOpenOutlivesOpenerOption = false; if ((disposition !== 'foreground-tab' && disposition !== 'new-window' && disposition !== 'background-tab')) { @@ -749,7 +749,7 @@ WebContents.prototype._init = function () { frameName, features: rawFeatures }, - closeWithOpener + outlivesOpener }); }); } diff --git a/lib/browser/guest-window-manager.ts b/lib/browser/guest-window-manager.ts index 6fad78ee6dc53..baa446ab91dae 100644 --- a/lib/browser/guest-window-manager.ts +++ b/lib/browser/guest-window-manager.ts @@ -29,7 +29,7 @@ const getGuestWindowByFrameName = (name: string) => frameNamesToWindow.get(name) * user to preventDefault() on the passed event (which ends up calling * DestroyWebContents). */ -export function openGuestWindow ({ event, embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, closeWithOpener }: { +export function openGuestWindow ({ event, embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, outlivesOpener }: { event: { sender: WebContents, defaultPrevented: boolean }, embedder: WebContents, guest?: WebContents, @@ -38,7 +38,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition postData?: PostData, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions, windowOpenArgs: WindowOpenArgs, - closeWithOpener: boolean, + outlivesOpener: boolean, }): BrowserWindow | undefined { const { url, frameName, features } = windowOpenArgs; const { options: browserWindowOptions } = makeBrowserWindowOptions({ @@ -78,7 +78,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition ...browserWindowOptions }); - handleWindowLifecycleEvents({ embedder, frameName, guest: window, closeWithOpener }); + handleWindowLifecycleEvents({ embedder, frameName, guest: window, outlivesOpener }); embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, referrer, postData }); @@ -91,11 +91,11 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition * too is the guest destroyed; this is Electron convention and isn't based in * browser behavior. */ -const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, closeWithOpener }: { +const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outlivesOpener }: { embedder: WebContents, guest: BrowserWindow, frameName: string, - closeWithOpener: boolean + outlivesOpener: boolean }) { const closedByEmbedder = function () { guest.removeListener('closed', closedByUser); @@ -104,11 +104,11 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, clos const closedByUser = function () { // Embedder might have been closed - if (!embedder.isDestroyed() && closeWithOpener) { + if (!embedder.isDestroyed() && !outlivesOpener) { embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder); } }; - if (closeWithOpener) { + if (!outlivesOpener) { embedder.once('current-render-view-deleted' as any, closedByEmbedder); } guest.once('closed', closedByUser); @@ -171,7 +171,7 @@ function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs, embedder: event.sender, guest: newGuest, frameName, - closeWithOpener: true + outlivesOpener: false }); } return true; diff --git a/typings/internal-electron.d.ts b/typings/internal-electron.d.ts index 04159553aad5f..a0d645440652f 100644 --- a/typings/internal-electron.d.ts +++ b/typings/internal-electron.d.ts @@ -63,7 +63,7 @@ declare namespace Electron { equal(other: WebContents): boolean; browserWindowOptions: BrowserWindowConstructorOptions; _windowOpenHandler: ((details: Electron.HandlerDetails) => any) | null; - _callWindowOpenHandler(event: any, details: Electron.HandlerDetails): {browserWindowConstructorOptions: Electron.BrowserWindowConstructorOptions | null, closeWithOpener: boolean}; + _callWindowOpenHandler(event: any, details: Electron.HandlerDetails): {browserWindowConstructorOptions: Electron.BrowserWindowConstructorOptions | null, outlivesOpener: boolean}; _setNextChildWebPreferences(prefs: Partial & Pick): void; _send(internal: boolean, channel: string, args: any): boolean; _sendToFrameInternal(frameId: number | [number, number], channel: string, ...args: any[]): boolean; From 3a1ae0a998e8c4c1c109f53d1fc6a100ef25f0e5 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Thu, 27 Jan 2022 09:59:19 -0800 Subject: [PATCH 8/9] dummy change to kick lint --- docs/api/window-open.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/window-open.md b/docs/api/window-open.md index 1925a5d1e7e5d..724b1fa16ff90 100644 --- a/docs/api/window-open.md +++ b/docs/api/window-open.md @@ -1,4 +1,4 @@ -# Opening windows from the renderer +# Opening windows from the renderer There are several ways to control how windows are created from trusted or untrusted content within a renderer. Windows can be created from the renderer in two ways: From 261e1b076c594ddf007b788286ededd83f88d681 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Thu, 27 Jan 2022 09:59:30 -0800 Subject: [PATCH 9/9] undo above --- docs/api/window-open.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/window-open.md b/docs/api/window-open.md index 724b1fa16ff90..1925a5d1e7e5d 100644 --- a/docs/api/window-open.md +++ b/docs/api/window-open.md @@ -1,4 +1,4 @@ -# Opening windows from the renderer +# Opening windows from the renderer There are several ways to control how windows are created from trusted or untrusted content within a renderer. Windows can be created from the renderer in two ways: