From 9aee85190caf9b736992eeddeb6c266adcac81fe Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Fri, 10 Jun 2022 01:42:04 +0200 Subject: [PATCH] chore: remove deprecated 'new-window' event --- .../new-window-web-contents-event.md | 3 - docs/api/web-contents.md | 58 ------- docs/api/webview-tag.md | 27 --- docs/breaking-changes.md | 18 ++ filenames.auto.gni | 1 - lib/browser/api/web-contents.ts | 8 - lib/browser/guest-view-manager.ts | 16 -- lib/browser/guest-window-manager.ts | 121 ++----------- spec-main/api-browser-window-spec.ts | 118 +------------ spec-main/api-web-contents-spec.ts | 22 --- .../snapshots/native-window-open.snapshot.txt | 161 ------------------ spec-main/guest-window-manager-spec.ts | 100 +---------- spec-main/webview-spec.ts | 47 ----- spec/ts-smoke/electron/renderer.ts | 5 - 14 files changed, 32 insertions(+), 673 deletions(-) delete mode 100644 docs/api/structures/new-window-web-contents-event.md delete mode 100644 spec-main/fixtures/snapshots/native-window-open.snapshot.txt diff --git a/docs/api/structures/new-window-web-contents-event.md b/docs/api/structures/new-window-web-contents-event.md deleted file mode 100644 index b56da02603b89..0000000000000 --- a/docs/api/structures/new-window-web-contents-event.md +++ /dev/null @@ -1,3 +0,0 @@ -# NewWindowWebContentsEvent Object extends `Event` - -* `newGuest` BrowserWindow (optional) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 71f223081bdd6..aa8c01d954c76 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -156,64 +156,6 @@ Returns: Emitted when page receives favicon urls. -#### Event: 'new-window' _Deprecated_ - -Returns: - -* `event` NewWindowWebContentsEvent -* `url` string -* `frameName` string -* `disposition` string - Can be `default`, `foreground-tab`, `background-tab`, - `new-window`, `save-to-disk` and `other`. -* `options` BrowserWindowConstructorOptions - The options which will be used for creating the new - [`BrowserWindow`](browser-window.md). -* `additionalFeatures` string[] - The non-standard features (features not handled - by Chromium or Electron) given to `window.open()`. Deprecated, and will now - always be the empty array `[]`. -* `referrer` [Referrer](structures/referrer.md) - The referrer that will be - passed to the new window. May or may not result in the `Referer` header being - sent, depending on the referrer policy. -* `postBody` [PostBody](structures/post-body.md) (optional) - The post data that - will be sent to the new window, along with the appropriate headers that will - be set. If no post data is to be sent, the value will be `null`. Only defined - when the window is being created by a form that set `target=_blank`. - -Deprecated in favor of [`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandlerhandler). - -Emitted when the page requests to open a new window for a `url`. It could be -requested by `window.open` or an external link like ``. - -By default a new `BrowserWindow` will be created for the `url`. - -Calling `event.preventDefault()` will prevent Electron from automatically creating a -new [`BrowserWindow`](browser-window.md). If you call `event.preventDefault()` and manually create a new -[`BrowserWindow`](browser-window.md) then you must set `event.newGuest` to reference the new [`BrowserWindow`](browser-window.md) -instance, failing to do so may result in unexpected behavior. For example: - -```javascript -myBrowserWindow.webContents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures, referrer, postBody) => { - event.preventDefault() - const win = new BrowserWindow({ - webContents: options.webContents, // use existing webContents if provided - show: false - }) - win.once('ready-to-show', () => win.show()) - if (!options.webContents) { - const loadOptions = { - httpReferrer: referrer - } - if (postBody != null) { - const { data, contentType, boundary } = postBody - loadOptions.postData = postBody.data - loadOptions.extraHeaders = `content-type: ${contentType}; boundary=${boundary}` - } - - win.loadURL(url, loadOptions) // existing webContents will be navigated automatically - } - event.newGuest = win -}) -``` - #### Event: 'did-create-window' Returns: diff --git a/docs/api/webview-tag.md b/docs/api/webview-tag.md index cc86a05d5be4d..499d348b4c507 100644 --- a/docs/api/webview-tag.md +++ b/docs/api/webview-tag.md @@ -805,33 +805,6 @@ const requestId = webview.findInPage('test') console.log(requestId) ``` -### Event: 'new-window' - -Returns: - -* `url` string -* `frameName` string -* `disposition` string - Can be `default`, `foreground-tab`, `background-tab`, - `new-window`, `save-to-disk` and `other`. -* `options` BrowserWindowConstructorOptions - The options which should be used for creating the new - [`BrowserWindow`](browser-window.md). - -Fired when the guest page attempts to open a new browser window. - -The following example code opens the new url in system's default browser. - -```javascript -const { shell } = require('electron') -const webview = document.querySelector('webview') - -webview.addEventListener('new-window', async (e) => { - const protocol = (new URL(e.url)).protocol - if (protocol === 'http:' || protocol === 'https:') { - await shell.openExternal(e.url) - } -}) -``` - ### Event: 'will-navigate' Returns: diff --git a/docs/breaking-changes.md b/docs/breaking-changes.md index c6c511b32bb18..85cdda0ff6c57 100644 --- a/docs/breaking-changes.md +++ b/docs/breaking-changes.md @@ -12,6 +12,24 @@ This document uses the following convention to categorize breaking changes: * **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release. * **Removed:** An API or feature was removed, and is no longer supported by Electron. +## Planned Breaking API Changes (21.0) + +### Removed: WebContents `new-window` event + +The `new-window` event of WebContents has been removed. It is replaced by [`webContents.setWindowOpenHandler()`](api/web-contents.md#contentssetwindowopenhandlerhandler). + +```js +// Removed in Electron 21 +webContents.on('new-window', (event) => { + event.preventDefault() +}) + +// Replace with +webContents.setWindowOpenHandler((details) => { + return { action: 'deny' } +}) +``` + ## Planned Breaking API Changes (20.0) ### Behavior Changed: V8 Memory Cage enabled diff --git a/filenames.auto.gni b/filenames.auto.gni index 2b865962a3885..6cbf6be5d0934 100644 --- a/filenames.auto.gni +++ b/filenames.auto.gni @@ -98,7 +98,6 @@ auto_filenames = { "docs/api/structures/mime-typed-buffer.md", "docs/api/structures/mouse-input-event.md", "docs/api/structures/mouse-wheel-input-event.md", - "docs/api/structures/new-window-web-contents-event.md", "docs/api/structures/notification-action.md", "docs/api/structures/notification-response.md", "docs/api/structures/payment-discount.md", diff --git a/lib/browser/api/web-contents.ts b/lib/browser/api/web-contents.ts index 61378c00dee37..dc9783cff6898 100644 --- a/lib/browser/api/web-contents.ts +++ b/lib/browser/api/web-contents.ts @@ -670,7 +670,6 @@ WebContents.prototype._init = function () { const options = result.browserWindowConstructorOptions; if (!event.defaultPrevented) { openGuestWindow({ - event, embedder: event.sender, disposition, referrer, @@ -717,13 +716,7 @@ WebContents.prototype._init = function () { transparent: windowOpenOverriddenOptions.transparent, ...windowOpenOverriddenOptions.webPreferences } : undefined; - // TODO(zcbenz): The features string is parsed twice: here where it is - // passed to C++, and in |makeBrowserWindowOptions| later where it is - // not actually used since the WebContents is created here. - // We should be able to remove the latter once the |new-window| event - // is removed. const { webPreferences: parsedWebPreferences } = parseFeatures(rawFeatures); - // Parameters should keep same with |makeBrowserWindowOptions|. const webPreferences = makeWebPreferences({ embedder: event.sender, insecureParsedWebPreferences: parsedWebPreferences, @@ -750,7 +743,6 @@ WebContents.prototype._init = function () { } openGuestWindow({ - event, embedder: event.sender, guest: webContents, overrideBrowserWindowOptions: overriddenOptions, diff --git a/lib/browser/guest-view-manager.ts b/lib/browser/guest-view-manager.ts index 2d88a0a017ea7..040aad33df483 100644 --- a/lib/browser/guest-view-manager.ts +++ b/lib/browser/guest-view-manager.ts @@ -22,13 +22,6 @@ const supportedWebViewEvents = Object.keys(webViewEvents); const guestInstances = new Map(); const embedderElementsMap = new Map(); -function sanitizeOptionsForGuest (options: Record) { - const ret = { ...options }; - // WebContents values can't be sent over IPC. - delete ret.webContents; - return ret; -} - function makeWebPreferences (embedder: Electron.WebContents, params: Record) { // parse the 'webpreferences' attribute string, if set // this uses the same parsing rules as window.open uses for its features @@ -156,15 +149,6 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n }); } - guest.on('new-window', function (event, url, frameName, disposition, options) { - sendToEmbedder(IPC_MESSAGES.GUEST_VIEW_INTERNAL_DISPATCH_EVENT, 'new-window', { - url, - frameName, - disposition, - options: sanitizeOptionsForGuest(options) - }); - }); - // Dispatch guest's IPC messages to embedder. guest.on('ipc-message-host' as any, function (event: Electron.IpcMainEvent, channel: string, args: any[]) { sendToEmbedder(IPC_MESSAGES.GUEST_VIEW_INTERNAL_DISPATCH_EVENT, 'ipc-message', { diff --git a/lib/browser/guest-window-manager.ts b/lib/browser/guest-window-manager.ts index 7aa91a15c9134..ef122bd8778bd 100644 --- a/lib/browser/guest-window-manager.ts +++ b/lib/browser/guest-window-manager.ts @@ -5,7 +5,7 @@ * out-of-process (cross-origin) are created here. "Embedder" roughly means * "parent." */ -import { BrowserWindow, deprecate } from 'electron/main'; +import { BrowserWindow } from 'electron/main'; import type { BrowserWindowConstructorOptions, Referrer, WebContents, LoadURLOptions } from 'electron/main'; import { parseFeatures } from '@electron/internal/browser/parse-features-string'; @@ -24,13 +24,8 @@ const getGuestWindowByFrameName = (name: string) => frameNamesToWindow.get(name) /** * `openGuestWindow` is called to create and setup event handling for the new * window. - * - * Until its removal in 12.0.0, the `new-window` event is fired, allowing the - * user to preventDefault() on the passed event (which ends up calling - * DestroyWebContents). */ -export function openGuestWindow ({ event, embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, outlivesOpener }: { - event: { sender: WebContents, defaultPrevented: boolean }, +export function openGuestWindow ({ embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, outlivesOpener }: { embedder: WebContents, guest?: WebContents, referrer: Referrer, @@ -41,23 +36,14 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition outlivesOpener: boolean, }): BrowserWindow | undefined { const { url, frameName, features } = windowOpenArgs; - const browserWindowOptions = makeBrowserWindowOptions({ - embedder, - features, - overrideOptions: overrideBrowserWindowOptions - }); - - const didCancelEvent = emitDeprecatedNewWindowEvent({ - event, - embedder, - guest, - browserWindowOptions, - windowOpenArgs, - disposition, - postData, - referrer - }); - if (didCancelEvent) return; + const { options: parsedOptions } = parseFeatures(features); + const browserWindowOptions = { + show: true, + width: 800, + height: 600, + ...parsedOptions, + ...overrideBrowserWindowOptions + }; // To spec, subsequent window.open calls with the same frame name (`target` in // spec parlance) will reuse the previous window. @@ -134,68 +120,6 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outl } }; -/** - * Deprecated in favor of `webContents.setWindowOpenHandler` and - * `did-create-window` in 11.0.0. Will be removed in 12.0.0. - */ -function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs, browserWindowOptions, disposition, referrer, postData }: { - event: { sender: WebContents, defaultPrevented: boolean, newGuest?: BrowserWindow }, - embedder: WebContents, - guest?: WebContents, - windowOpenArgs: WindowOpenArgs, - browserWindowOptions: BrowserWindowConstructorOptions, - disposition: string, - referrer: Referrer, - postData?: PostData, -}): boolean { - const { url, frameName } = windowOpenArgs; - const isWebViewWithPopupsDisabled = embedder.getType() === 'webview' && embedder.getLastWebPreferences()!.disablePopups; - const postBody = postData ? { - data: postData, - ...parseContentTypeFormat(postData) - } : null; - - if (embedder.listenerCount('new-window') > 0) { - deprecate.log('The new-window event is deprecated and will be removed. Please use contents.setWindowOpenHandler() instead.'); - } - - embedder.emit( - 'new-window', - event, - url, - frameName, - disposition, - { - ...browserWindowOptions, - webContents: guest - }, - [], // additionalFeatures - referrer, - postBody - ); - - const { newGuest } = event; - if (isWebViewWithPopupsDisabled) return true; - if (event.defaultPrevented) { - if (newGuest) { - if (guest === newGuest.webContents) { - // The webContents is not changed, so set defaultPrevented to false to - // stop the callers of this event from destroying the webContents. - event.defaultPrevented = false; - } - - handleWindowLifecycleEvents({ - embedder: event.sender, - guest: newGuest, - frameName, - outlivesOpener: false - }); - } - return true; - } - return false; -} - // Security options that child windows will always inherit from parent windows const securityWebPreferences: { [key: string]: boolean } = { contextIsolation: true, @@ -207,31 +131,6 @@ const securityWebPreferences: { [key: string]: boolean } = { enableWebSQL: false }; -function makeBrowserWindowOptions ({ embedder, features, overrideOptions }: { - embedder: WebContents, - features: string, - overrideOptions?: BrowserWindowConstructorOptions, -}) { - const { options: parsedOptions, webPreferences: parsedWebPreferences } = parseFeatures(features); - - return { - show: true, - width: 800, - height: 600, - ...parsedOptions, - ...overrideOptions, - // Note that for normal code path an existing WebContents created by - // Chromium will be used, with web preferences parsed in the - // |-will-add-new-contents| event. - // The |webPreferences| here is only used by the |new-window| event. - webPreferences: makeWebPreferences({ - embedder, - insecureParsedWebPreferences: parsedWebPreferences, - secureOverrideWebPreferences: overrideOptions && overrideOptions.webPreferences - }) - } as Electron.BrowserViewConstructorOptions; -} - export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {}, insecureParsedWebPreferences: parsedWebPreferences = {} }: { embedder: WebContents, insecureParsedWebPreferences?: ReturnType['webPreferences'], diff --git a/spec-main/api-browser-window-spec.ts b/spec-main/api-browser-window-spec.ts index 6be93a0fea768..a0cf1f5b98614 100644 --- a/spec-main/api-browser-window-spec.ts +++ b/spec-main/api-browser-window-spec.ts @@ -5,7 +5,7 @@ import * as fs from 'fs'; import * as qs from 'querystring'; import * as http from 'http'; import { AddressInfo } from 'net'; -import { app, BrowserWindow, BrowserView, dialog, ipcMain, OnBeforeSendHeadersListenerDetails, protocol, screen, webContents, session, WebContents, BrowserWindowConstructorOptions } from 'electron/main'; +import { app, BrowserWindow, BrowserView, dialog, ipcMain, OnBeforeSendHeadersListenerDetails, protocol, screen, webContents, session, WebContents } from 'electron/main'; import { emittedOnce, emittedUntil, emittedNTimes } from './events-helpers'; import { ifit, ifdescribe, defer, delay } from './spec-helpers'; @@ -3080,7 +3080,7 @@ describe('BrowserWindow module', () => { expect(argv).to.include('--enable-sandbox'); }); - it('should open windows with the options configured via new-window event listeners', async () => { + it('should open windows with the options configured via setWindowOpenHandler handlers', async () => { const w = new BrowserWindow({ show: false, webPreferences: { @@ -3171,30 +3171,6 @@ describe('BrowserWindow module', () => { }); }); - it('supports calling preventDefault on new-window events', (done) => { - const w = new BrowserWindow({ - show: false, - webPreferences: { - sandbox: true - } - }); - const initialWebContents = webContents.getAllWebContents().map((i) => i.id); - w.webContents.once('new-window', (e) => { - e.preventDefault(); - // We need to give it some time so the windows get properly disposed (at least on OSX). - setTimeout(() => { - const currentWebContents = webContents.getAllWebContents().map((i) => i.id); - try { - expect(currentWebContents).to.deep.equal(initialWebContents); - done(); - } catch (error) { - done(e); - } - }, 100); - }); - w.loadFile(path.join(fixtures, 'pages', 'window-open.html')); - }); - it('validates process APIs access in sandboxed renderer', async () => { const w = new BrowserWindow({ show: false, @@ -3350,7 +3326,7 @@ describe('BrowserWindow module', () => { w.loadFile(path.join(fixtures, 'api', 'new-window-webview.html')); await webviewLoaded; }); - it('should open windows with the options configured via new-window event listeners', async () => { + it('should open windows with the options configured via setWindowOpenHandler handlers', async () => { const preloadPath = path.join(mainFixtures, 'api', 'new-window-preload.js'); w.webContents.setWindowOpenHandler(() => ({ action: 'allow', @@ -3720,94 +3696,6 @@ describe('BrowserWindow module', () => { }); }); - describe('new-window event', () => { - afterEach(closeAllWindows); - - it('emits when window.open is called', (done) => { - const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } }); - w.webContents.once('new-window', (e, url, frameName, disposition, options) => { - e.preventDefault(); - try { - expect(url).to.equal('http://host/'); - expect(frameName).to.equal('host'); - expect((options as any)['this-is-not-a-standard-feature']).to.equal(true); - done(); - } catch (e) { - done(e); - } - }); - w.loadFile(path.join(fixtures, 'pages', 'window-open.html')); - }); - - it('emits when window.open is called with no webPreferences', (done) => { - const w = new BrowserWindow({ show: false }); - w.webContents.once('new-window', function (e, url, frameName, disposition, options) { - e.preventDefault(); - try { - expect(url).to.equal('http://host/'); - expect(frameName).to.equal('host'); - expect((options as any)['this-is-not-a-standard-feature']).to.equal(true); - done(); - } catch (e) { - done(e); - } - }); - w.loadFile(path.join(fixtures, 'pages', 'window-open.html')); - }); - - it('emits when link with target is called', (done) => { - const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } }); - w.webContents.once('new-window', (e, url, frameName) => { - e.preventDefault(); - try { - expect(url).to.equal('http://host/'); - expect(frameName).to.equal('target'); - done(); - } catch (e) { - done(e); - } - }); - w.loadFile(path.join(fixtures, 'pages', 'target-name.html')); - }); - - it('includes all properties', async () => { - const w = new BrowserWindow({ show: false }); - - const p = new Promise<{ - url: string, - frameName: string, - disposition: string, - options: BrowserWindowConstructorOptions, - additionalFeatures: string[], - referrer: Electron.Referrer, - postBody: Electron.PostBody - }>((resolve) => { - w.webContents.once('new-window', (e, url, frameName, disposition, options, additionalFeatures, referrer, postBody) => { - e.preventDefault(); - resolve({ url, frameName, disposition, options, additionalFeatures, referrer, postBody }); - }); - }); - w.loadURL(`data:text/html,${encodeURIComponent(` -
- -
- - `)}`); - const { url, frameName, disposition, options, additionalFeatures, referrer, postBody } = await p; - expect(url).to.equal('http://example.com/test'); - expect(frameName).to.equal(''); - expect(disposition).to.equal('foreground-tab'); - expect(options).to.be.an('object').not.null(); - expect(referrer.policy).to.equal('strict-origin-when-cross-origin'); - expect(referrer.url).to.equal(''); - expect(additionalFeatures).to.deep.equal([]); - expect(postBody.data).to.have.length(1); - expect(postBody.data[0].type).to.equal('rawData'); - expect((postBody.data[0] as any).bytes).to.deep.equal(Buffer.from('post-test-key=post-test-value')); - expect(postBody.contentType).to.equal('application/x-www-form-urlencoded'); - }); - }); - ifdescribe(process.platform !== 'linux')('max/minimize events', () => { afterEach(closeAllWindows); it('emits an event when window is maximized', async () => { diff --git a/spec-main/api-web-contents-spec.ts b/spec-main/api-web-contents-spec.ts index 3050b926988a6..e2b57a3eb752f 100644 --- a/spec-main/api-web-contents-spec.ts +++ b/spec-main/api-web-contents-spec.ts @@ -2102,26 +2102,4 @@ describe('webContents module', () => { expect(params.y).to.be.a('number'); }); }); - - it('emits a cancelable event before creating a child webcontents', async () => { - const w = new BrowserWindow({ - show: false, - webPreferences: { - sandbox: true - } - }); - w.webContents.on('-will-add-new-contents' as any, (event: any, url: any) => { - expect(url).to.equal('about:blank'); - event.preventDefault(); - }); - let wasCalled = false; - w.webContents.on('new-window' as any, () => { - wasCalled = true; - }); - await w.loadURL('about:blank'); - await w.webContents.executeJavaScript('window.open(\'about:blank\')'); - await new Promise((resolve) => { process.nextTick(resolve); }); - expect(wasCalled).to.equal(false); - await closeAllWindows(); - }); }); diff --git a/spec-main/fixtures/snapshots/native-window-open.snapshot.txt b/spec-main/fixtures/snapshots/native-window-open.snapshot.txt deleted file mode 100644 index fcc4a9885ef58..0000000000000 --- a/spec-main/fixtures/snapshots/native-window-open.snapshot.txt +++ /dev/null @@ -1,161 +0,0 @@ -[ - [ - "top=5,left=10,resizable=no", - { - "sender": "[WebContents]" - }, - "about:blank", - "frame-name", - "new-window", - { - "show": true, - "width": 800, - "height": 600, - "top": 5, - "left": 10, - "resizable": false, - "x": 10, - "y": 5, - "webPreferences": { - "contextIsolation": true, - "nodeIntegration": false, - "sandbox": true, - "webviewTag": false, - "nodeIntegrationInSubFrames": false - }, - "webContents": "[WebContents]" - }, - [], - { - "url": "", - "policy": "strict-origin-when-cross-origin" - }, - null - ], - [ - "zoomFactor=2,resizable=0,x=0,y=10", - { - "sender": "[WebContents]" - }, - "about:blank", - "frame-name", - "new-window", - { - "show": true, - "width": 800, - "height": 600, - "resizable": false, - "x": 0, - "y": 10, - "webPreferences": { - "zoomFactor": "2", - "contextIsolation": true, - "nodeIntegration": false, - "sandbox": true, - "webviewTag": false, - "nodeIntegrationInSubFrames": false - }, - "webContents": "[WebContents]" - }, - [], - { - "url": "", - "policy": "strict-origin-when-cross-origin" - }, - null - ], - [ - "backgroundColor=gray,webPreferences=0,x=100,y=100", - { - "sender": "[WebContents]" - }, - "about:blank", - "frame-name", - "new-window", - { - "show": true, - "width": 800, - "height": 600, - "backgroundColor": "gray", - "webPreferences": { - "contextIsolation": true, - "nodeIntegration": false, - "sandbox": true, - "webviewTag": false, - "nodeIntegrationInSubFrames": false - }, - "x": 100, - "y": 100, - "webContents": "[WebContents]" - }, - [], - { - "url": "", - "policy": "strict-origin-when-cross-origin" - }, - null - ], - [ - "x=50,y=20,title=sup", - { - "sender": "[WebContents]" - }, - "about:blank", - "frame-name", - "new-window", - { - "show": true, - "width": 800, - "height": 600, - "x": 50, - "y": 20, - "title": "sup", - "webPreferences": { - "contextIsolation": true, - "nodeIntegration": false, - "sandbox": true, - "webviewTag": false, - "nodeIntegrationInSubFrames": false - }, - "webContents": "[WebContents]" - }, - [], - { - "url": "", - "policy": "strict-origin-when-cross-origin" - }, - null - ], - [ - "show=false,top=1,left=1", - { - "sender": "[WebContents]" - }, - "about:blank", - "frame-name", - "new-window", - { - "show": false, - "width": 800, - "height": 600, - "top": 1, - "left": 1, - "x": 1, - "y": 1, - "webPreferences": { - "contextIsolation": true, - "nodeIntegration": false, - "sandbox": true, - "webviewTag": false, - "nodeIntegrationInSubFrames": false - }, - "webContents": "[WebContents]" - }, - [], - { - "url": "", - "policy": "strict-origin-when-cross-origin" - }, - null - ] -] diff --git a/spec-main/guest-window-manager-spec.ts b/spec-main/guest-window-manager-spec.ts index 974e8fce452c2..7eaa99d6d024f 100644 --- a/spec-main/guest-window-manager-spec.ts +++ b/spec-main/guest-window-manager-spec.ts @@ -1,75 +1,8 @@ import { BrowserWindow } from 'electron'; -import { writeFileSync, readFileSync } from 'fs'; -import { resolve } from 'path'; import { expect, assert } from 'chai'; import { closeAllWindows } from './window-helpers'; const { emittedOnce } = require('./events-helpers'); -function genSnapshot (browserWindow: BrowserWindow, features: string) { - return new Promise((resolve) => { - browserWindow.webContents.on('new-window', (...args: any[]) => { - resolve([features, ...args]); - }); - browserWindow.webContents.executeJavaScript(`window.open('about:blank', 'frame-name', '${features}') && true`); - }); -} - -describe('new-window event', () => { - const snapshotFileName = 'native-window-open.snapshot.txt'; - const browserWindowOptions = { - show: false, - width: 200, - title: 'cool', - backgroundColor: 'blue', - focusable: false, - webPreferences: { - sandbox: true - } - }; - - const snapshotFile = resolve(__dirname, 'fixtures', 'snapshots', snapshotFileName); - let browserWindow: BrowserWindow; - let existingSnapshots: any[]; - - before(() => { - existingSnapshots = parseSnapshots(readFileSync(snapshotFile, { encoding: 'utf8' })); - }); - - beforeEach((done) => { - browserWindow = new BrowserWindow(browserWindowOptions); - browserWindow.loadURL('about:blank'); - browserWindow.on('ready-to-show', () => { done(); }); - }); - - afterEach(closeAllWindows); - - const newSnapshots: any[] = []; - [ - 'top=5,left=10,resizable=no', - 'zoomFactor=2,resizable=0,x=0,y=10', - 'backgroundColor=gray,webPreferences=0,x=100,y=100', - 'x=50,y=20,title=sup', - 'show=false,top=1,left=1' - ].forEach((features, index) => { - /** - * ATTN: If this test is failing, you likely just need to change - * `shouldOverwriteSnapshot` to true and then evaluate the snapshot diff - * to see if the change is harmless. - */ - it(`matches snapshot for ${features}`, async () => { - const newSnapshot = await genSnapshot(browserWindow, features); - newSnapshots.push(newSnapshot); - // TODO: The output when these fail could be friendlier. - expect(stringifySnapshots(newSnapshot)).to.equal(stringifySnapshots(existingSnapshots[index])); - }); - }); - - after(() => { - const shouldOverwriteSnapshot = false; - if (shouldOverwriteSnapshot) writeFileSync(snapshotFile, stringifySnapshots(newSnapshots, true)); - }); -}); - describe('webContents.setWindowOpenHandler', () => { let browserWindow: BrowserWindow; beforeEach(async () => { @@ -138,9 +71,6 @@ describe('webContents.setWindowOpenHandler', () => { return { action: 'deny' }; }); }); - browserWindow.webContents.on('new-window', () => { - assert.fail('new-window should not be called with an overridden window.open'); - }); browserWindow.webContents.on('did-create-window', () => { assert.fail('did-create-window should not be called with an overridden window.open'); @@ -158,9 +88,6 @@ describe('webContents.setWindowOpenHandler', () => { return { action: 'deny' }; }); }); - browserWindow.webContents.on('new-window', () => { - assert.fail('new-window should not be called with an overridden window.open'); - }); browserWindow.webContents.on('did-create-window', () => { assert.fail('did-create-window should not be called with an overridden window.open'); @@ -180,9 +107,6 @@ describe('webContents.setWindowOpenHandler', () => { return { action: 'deny' }; }); }); - browserWindow.webContents.on('new-window', () => { - assert.fail('new-window should not be called with an overridden window.open'); - }); browserWindow.webContents.on('did-create-window', () => { assert.fail('did-create-window should not be called with an overridden window.open'); @@ -257,10 +181,7 @@ describe('webContents.setWindowOpenHandler', () => { browserWindow.webContents.executeJavaScript("window.open('about:blank', '', 'show=no') && true"); }); - await Promise.all([ - emittedOnce(browserWindow.webContents, 'did-create-window'), - emittedOnce(browserWindow.webContents, 'new-window') - ]); + await emittedOnce(browserWindow.webContents, 'did-create-window'); }); it('can change webPreferences of child windows', (done) => { @@ -282,22 +203,3 @@ describe('webContents.setWindowOpenHandler', () => { expect(await browserWindow.webContents.executeJavaScript('42')).to.equal(42); }); }); - -function stringifySnapshots (snapshots: any, pretty = false) { - return JSON.stringify(snapshots, (key, value) => { - if (['sender', 'webContents'].includes(key)) { - return '[WebContents]'; - } - if (key === 'processId' && typeof value === 'number') { - return 'placeholder-process-id'; - } - if (key === 'returnValue') { - return 'placeholder-guest-contents-id'; - } - return value; - }, pretty ? 2 : undefined); -} - -function parseSnapshots (snapshotsJson: string) { - return JSON.parse(snapshotsJson); -} diff --git a/spec-main/webview-spec.ts b/spec-main/webview-spec.ts index ade63be8c8098..444a9cea618bd 100644 --- a/spec-main/webview-spec.ts +++ b/spec-main/webview-spec.ts @@ -668,31 +668,6 @@ describe(' tag', function () { expect(content).to.equal(expectedContent); }); - it('emits a new-window event', async () => { - // Don't wait for loading to finish. - const attributes = { - allowpopups: 'on', - nodeintegration: 'on', - webpreferences: 'contextIsolation=no', - src: `file://${fixtures}/pages/window-open.html` - }; - const { url, frameName } = await w.webContents.executeJavaScript(` - new Promise((resolve, reject) => { - const webview = document.createElement('webview') - for (const [k, v] of Object.entries(${JSON.stringify(attributes)})) { - webview.setAttribute(k, v) - } - document.body.appendChild(webview) - webview.addEventListener('new-window', (e) => { - resolve({url: e.url, frameName: e.frameName}) - }) - }) - `); - - expect(url).to.equal('http://host/'); - expect(frameName).to.equal('host'); - }); - it('emits a browser-window-created event', async () => { // Don't wait for loading to finish. loadWebView(w.webContents, { @@ -1435,28 +1410,6 @@ describe(' tag', function () { }); after(closeAllWindows); - describe('new-window event', () => { - it('emits when window.open is called', async () => { - const { url, frameName } = await loadWebViewAndWaitForEvent(w, { - src: `file://${fixtures}/pages/window-open.html`, - allowpopups: 'true' - }, 'new-window'); - - expect(url).to.equal('http://host/'); - expect(frameName).to.equal('host'); - }); - - it('emits when link with target is called', async () => { - const { url, frameName } = await loadWebViewAndWaitForEvent(w, { - src: `file://${fixtures}/pages/target-name.html`, - allowpopups: 'true' - }, 'new-window'); - - expect(url).to.equal('http://host/'); - expect(frameName).to.equal('target'); - }); - }); - describe('ipc-message event', () => { it('emits when guest sends an ipc message to browser', async () => { const { frameId, channel, args } = await loadWebViewAndWaitForEvent(w, { diff --git a/spec/ts-smoke/electron/renderer.ts b/spec/ts-smoke/electron/renderer.ts index 16bc8d2c51b01..cef883bebe047 100644 --- a/spec/ts-smoke/electron/renderer.ts +++ b/spec/ts-smoke/electron/renderer.ts @@ -174,11 +174,6 @@ webview.addEventListener('found-in-page', function (e) { const requestId = webview.findInPage('test') -webview.addEventListener('new-window', async e => { - const { shell } = require('electron') - await shell.openExternal(e.url) -}) - webview.addEventListener('close', function () { webview.src = 'about:blank' })