feat: set app.enableRendererProcessReuse to true by default (#22336)
* feat: set app.enableRendererProcessReuse to true by default * chore: add context aware info to breaking changes doc * spec: fix nodeIntegration in child windows test for rendererprocessreuse * spec: fix remote listeners in destroyed renderers spec as the error is now async * Update api-browser-window-spec.ts * chore: deprecate affinity * chore: fix docs * spec: handle tests crashing without an exist code * spec: update tests for new rendererprocessreuse default * spec: with renderer process re-use we get to destroy less views
This commit is contained in:
parent
7a91078cc7
commit
7b7def7d1e
10 changed files with 146 additions and 103 deletions
|
@ -289,7 +289,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||||
between the web pages even when you specified different values for them,
|
between the web pages even when you specified different values for them,
|
||||||
including but not limited to `preload`, `sandbox` and `nodeIntegration`.
|
including but not limited to `preload`, `sandbox` and `nodeIntegration`.
|
||||||
So it is suggested to use exact same `webPreferences` for web pages with
|
So it is suggested to use exact same `webPreferences` for web pages with
|
||||||
the same `affinity`. _This property is experimental_
|
the same `affinity`. _Deprecated_
|
||||||
* `zoomFactor` Number (optional) - The default zoom factor of the page, `3.0` represents
|
* `zoomFactor` Number (optional) - The default zoom factor of the page, `3.0` represents
|
||||||
`300%`. Default is `1.0`.
|
`300%`. Default is `1.0`.
|
||||||
* `javascript` Boolean (optional) - Enables JavaScript support. Default is `true`.
|
* `javascript` Boolean (optional) - Enables JavaScript support. Default is `true`.
|
||||||
|
|
|
@ -1,62 +1,62 @@
|
||||||
## Class: ServiceWorkers
|
## Class: ServiceWorkers
|
||||||
|
|
||||||
> Query and receive events from a sessions active service workers.
|
> Query and receive events from a sessions active service workers.
|
||||||
|
|
||||||
Process: [Main](../glossary.md#main-process)
|
Process: [Main](../glossary.md#main-process)
|
||||||
|
|
||||||
Instances of the `ServiceWorkers` class are accessed by using `serviceWorkers` property of
|
Instances of the `ServiceWorkers` class are accessed by using `serviceWorkers` property of
|
||||||
a `Session`.
|
a `Session`.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { session } = require('electron')
|
const { session } = require('electron')
|
||||||
|
|
||||||
// Get all service workers.
|
// Get all service workers.
|
||||||
console.log(session.defaultSession.serviceWorkers.getAllRunning())
|
console.log(session.defaultSession.serviceWorkers.getAllRunning())
|
||||||
|
|
||||||
// Handle logs and get service worker info
|
// Handle logs and get service worker info
|
||||||
session.defaultSession.serviceWorkers.on('console-message', (event, messageDetails) => {
|
session.defaultSession.serviceWorkers.on('console-message', (event, messageDetails) => {
|
||||||
console.log(
|
console.log(
|
||||||
'Got service worker message',
|
'Got service worker message',
|
||||||
messageDetails,
|
messageDetails,
|
||||||
'from',
|
'from',
|
||||||
session.defaultSession.serviceWorkers.getFromVersionID(messageDetails.versionId)
|
session.defaultSession.serviceWorkers.getFromVersionID(messageDetails.versionId)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### Instance Events
|
### Instance Events
|
||||||
|
|
||||||
The following events are available on instances of `ServiceWorkers`:
|
The following events are available on instances of `ServiceWorkers`:
|
||||||
|
|
||||||
#### Event: 'console-message'
|
#### Event: 'console-message'
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
* `event` Event
|
* `event` Event
|
||||||
* `messageDetails` Object - Information about the console message
|
* `messageDetails` Object - Information about the console message
|
||||||
* `message` String - The actual console message
|
* `message` String - The actual console message
|
||||||
* `versionId` Number - The version ID of the service worker that sent the log message
|
* `versionId` Number - The version ID of the service worker that sent the log message
|
||||||
* `source` String - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `app-cache`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
|
* `source` String - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `app-cache`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
|
||||||
* `level` Number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
|
* `level` Number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
|
||||||
* `sourceUrl` String - The URL the message came from
|
* `sourceUrl` String - The URL the message came from
|
||||||
* `lineNumber` Number - The line number of the source that triggered this console message
|
* `lineNumber` Number - The line number of the source that triggered this console message
|
||||||
|
|
||||||
Emitted when a service worker logs something to the console.
|
Emitted when a service worker logs something to the console.
|
||||||
|
|
||||||
### Instance Methods
|
### Instance Methods
|
||||||
|
|
||||||
The following methods are available on instances of `ServiceWorkers`:
|
The following methods are available on instances of `ServiceWorkers`:
|
||||||
|
|
||||||
#### `serviceWorkers.getAllRunning()`
|
#### `serviceWorkers.getAllRunning()`
|
||||||
|
|
||||||
Returns `Record<Number, ServiceWorkerInfo>` - A [ServiceWorkerInfo](structures/service-worker-info.md) object where the keys are the service worker version ID and the values are the information about that service worker.
|
Returns `Record<Number, ServiceWorkerInfo>` - A [ServiceWorkerInfo](structures/service-worker-info.md) object where the keys are the service worker version ID and the values are the information about that service worker.
|
||||||
|
|
||||||
#### `serviceWorkers.getFromVersionID(versionId)`
|
#### `serviceWorkers.getFromVersionID(versionId)`
|
||||||
|
|
||||||
* `versionId` Number
|
* `versionId` Number
|
||||||
|
|
||||||
Returns [`ServiceWorkerInfo`](structures/service-worker-info.md) - Information about this service worker
|
Returns [`ServiceWorkerInfo`](structures/service-worker-info.md) - Information about this service worker
|
||||||
|
|
||||||
If the service worker does not exist or is not running this method will throw an exception.
|
If the service worker does not exist or is not running this method will throw an exception.
|
||||||
|
|
|
@ -8,6 +8,14 @@ The `FIXME` string is used in code comments to denote things that should be fixe
|
||||||
|
|
||||||
## Planned Breaking API Changes (10.0)
|
## Planned Breaking API Changes (10.0)
|
||||||
|
|
||||||
|
### Browser Window Affinity
|
||||||
|
|
||||||
|
The `affinity` option when constructing a new `BrowserWindow` will be removed
|
||||||
|
as part of our plan to more closely align with Chromiums process model for security,
|
||||||
|
performance and maintainability.
|
||||||
|
|
||||||
|
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
|
||||||
|
|
||||||
### `enableRemoteModule` defaults to `false`
|
### `enableRemoteModule` defaults to `false`
|
||||||
|
|
||||||
In Electron 9, using the remote module without explicitly enabling it via the
|
In Electron 9, using the remote module without explicitly enabling it via the
|
||||||
|
@ -28,6 +36,18 @@ module](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-
|
||||||
|
|
||||||
## Planned Breaking API Changes (9.0)
|
## Planned Breaking API Changes (9.0)
|
||||||
|
|
||||||
|
### Loading non-context-aware native modules in the renderer process
|
||||||
|
|
||||||
|
As of Electron 9 we do not allow loading of non-context-aware native modules in
|
||||||
|
the renderer process. This is to improve security, performance and maintainability
|
||||||
|
of Electron as a project.
|
||||||
|
|
||||||
|
If this impacts you, you can temporarily set `app.allowRendererProcessReuse` to `false`
|
||||||
|
to revert to the old behavior. This flag will only be an option until Electron 11 so
|
||||||
|
you should plan to update your native modules to be context aware.
|
||||||
|
|
||||||
|
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
|
||||||
|
|
||||||
### `<webview>.getWebContents()`
|
### `<webview>.getWebContents()`
|
||||||
|
|
||||||
This API, which was deprecated in Electron 8.0, is now removed.
|
This API, which was deprecated in Electron 8.0, is now removed.
|
||||||
|
|
|
@ -203,13 +203,17 @@ async function runMainProcessElectronTests () {
|
||||||
exe = 'python'
|
exe = 'python'
|
||||||
}
|
}
|
||||||
|
|
||||||
const { status } = childProcess.spawnSync(exe, runnerArgs, {
|
const { status, signal } = childProcess.spawnSync(exe, runnerArgs, {
|
||||||
cwd: path.resolve(__dirname, '../..'),
|
cwd: path.resolve(__dirname, '../..'),
|
||||||
stdio: 'inherit'
|
stdio: 'inherit'
|
||||||
})
|
})
|
||||||
if (status !== 0) {
|
if (status !== 0) {
|
||||||
const textStatus = process.platform === 'win32' ? `0x${status.toString(16)}` : status.toString()
|
if (status) {
|
||||||
console.log(`${fail} Electron tests failed with code ${textStatus}.`)
|
const textStatus = process.platform === 'win32' ? `0x${status.toString(16)}` : status.toString()
|
||||||
|
console.log(`${fail} Electron tests failed with code ${textStatus}.`)
|
||||||
|
} else {
|
||||||
|
console.log(`${fail} Electron tests failed with kill signal ${signal}.`)
|
||||||
|
}
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
console.log(`${pass} Electron main process tests passed.`)
|
console.log(`${pass} Electron main process tests passed.`)
|
||||||
|
|
|
@ -309,7 +309,7 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
|
||||||
|
|
||||||
std::string user_agent_override_ = "";
|
std::string user_agent_override_ = "";
|
||||||
|
|
||||||
bool disable_process_restart_tricks_ = false;
|
bool disable_process_restart_tricks_ = true;
|
||||||
|
|
||||||
// Simple shared ID generator, used by ProxyingURLLoaderFactory and
|
// Simple shared ID generator, used by ProxyingURLLoaderFactory and
|
||||||
// ProxyingWebSocket classes.
|
// ProxyingWebSocket classes.
|
||||||
|
|
|
@ -1423,8 +1423,8 @@ describe('default behavior', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('app.allowRendererProcessReuse', () => {
|
describe('app.allowRendererProcessReuse', () => {
|
||||||
it('should default to false', () => {
|
it('should default to true', () => {
|
||||||
expect(app.allowRendererProcessReuse).to.equal(false)
|
expect(app.allowRendererProcessReuse).to.equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should cause renderer processes to get new PIDs when false', async () => {
|
it('should cause renderer processes to get new PIDs when false', async () => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
|
||||||
import { ipcMain, BrowserWindow, WebPreferences } from 'electron'
|
import { ipcMain, BrowserWindow, WebPreferences, app } from 'electron'
|
||||||
import { closeWindow } from './window-helpers'
|
import { closeWindow } from './window-helpers'
|
||||||
|
|
||||||
describe('BrowserWindow with affinity module', () => {
|
describe('BrowserWindow with affinity module', () => {
|
||||||
|
@ -10,6 +10,14 @@ describe('BrowserWindow with affinity module', () => {
|
||||||
const myAffinityNameUpper = 'MYAFFINITY'
|
const myAffinityNameUpper = 'MYAFFINITY'
|
||||||
const anotherAffinityName = 'anotherAffinity'
|
const anotherAffinityName = 'anotherAffinity'
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
app.allowRendererProcessReuse = false
|
||||||
|
})
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
app.allowRendererProcessReuse = true
|
||||||
|
})
|
||||||
|
|
||||||
async function createWindowWithWebPrefs (webPrefs: WebPreferences) {
|
async function createWindowWithWebPrefs (webPrefs: WebPreferences) {
|
||||||
const w = new BrowserWindow({
|
const w = new BrowserWindow({
|
||||||
show: false,
|
show: false,
|
||||||
|
|
|
@ -2406,18 +2406,6 @@ describe('BrowserWindow module', () => {
|
||||||
const webPreferences = (childWebContents as any).getLastWebPreferences()
|
const webPreferences = (childWebContents as any).getLastWebPreferences()
|
||||||
expect(webPreferences.foo).to.equal('bar')
|
expect(webPreferences.foo).to.equal('bar')
|
||||||
})
|
})
|
||||||
it('should have nodeIntegration disabled in child windows', async () => {
|
|
||||||
const w = new BrowserWindow({
|
|
||||||
show: false,
|
|
||||||
webPreferences: {
|
|
||||||
nodeIntegration: true,
|
|
||||||
nativeWindowOpen: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
w.loadFile(path.join(fixtures, 'api', 'native-window-open-argv.html'))
|
|
||||||
const [, typeofProcess] = await emittedOnce(ipcMain, 'answer')
|
|
||||||
expect(typeofProcess).to.eql('undefined')
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('window.location', () => {
|
describe('window.location', () => {
|
||||||
const protocols = [
|
const protocols = [
|
||||||
|
|
|
@ -246,9 +246,17 @@ ifdescribe(features.isRemoteModuleEnabled())('remote module', () => {
|
||||||
expect(w.webContents.listenerCount('remote-handler')).to.equal(2)
|
expect(w.webContents.listenerCount('remote-handler')).to.equal(2)
|
||||||
let warnMessage: string | null = null
|
let warnMessage: string | null = null
|
||||||
const originalWarn = console.warn
|
const originalWarn = console.warn
|
||||||
|
let warned: Function
|
||||||
|
const warnPromise = new Promise(resolve => {
|
||||||
|
warned = resolve
|
||||||
|
})
|
||||||
try {
|
try {
|
||||||
console.warn = (message: string) => { warnMessage = message }
|
console.warn = (message: string) => {
|
||||||
|
warnMessage = message
|
||||||
|
warned()
|
||||||
|
}
|
||||||
w.webContents.emit('remote-handler', { sender: w.webContents })
|
w.webContents.emit('remote-handler', { sender: w.webContents })
|
||||||
|
await warnPromise
|
||||||
} finally {
|
} finally {
|
||||||
console.warn = originalWarn
|
console.warn = originalWarn
|
||||||
}
|
}
|
||||||
|
|
|
@ -963,29 +963,44 @@ describe('webContents module', () => {
|
||||||
w.loadFile(path.join(fixturesPath, 'pages', 'webframe-zoom.html'))
|
w.loadFile(path.join(fixturesPath, 'pages', 'webframe-zoom.html'))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('cannot persist zoom level after navigation with webFrame', (done) => {
|
describe('with unique domains', () => {
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } })
|
let server: http.Server
|
||||||
let initialNavigation = true
|
let serverUrl: string
|
||||||
const source = `
|
let crossSiteUrl: string
|
||||||
const {ipcRenderer, webFrame} = require('electron')
|
|
||||||
webFrame.setZoomLevel(0.6)
|
before((done) => {
|
||||||
ipcRenderer.send('zoom-level-set', webFrame.getZoomLevel())
|
server = http.createServer((req, res) => {
|
||||||
`
|
setTimeout(() => res.end('hey'), 0)
|
||||||
w.webContents.on('did-finish-load', () => {
|
})
|
||||||
if (initialNavigation) {
|
server.listen(0, '127.0.0.1', () => {
|
||||||
w.webContents.executeJavaScript(source)
|
serverUrl = `http://127.0.0.1:${(server.address() as AddressInfo).port}`
|
||||||
} else {
|
crossSiteUrl = `http://localhost:${(server.address() as AddressInfo).port}`
|
||||||
const zoomLevel = w.webContents.zoomLevel
|
|
||||||
expect(zoomLevel).to.equal(0)
|
|
||||||
done()
|
done()
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
ipcMain.once('zoom-level-set', (e, zoomLevel) => {
|
|
||||||
|
after(() => {
|
||||||
|
server.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('cannot persist zoom level after navigation with webFrame', async () => {
|
||||||
|
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } })
|
||||||
|
const source = `
|
||||||
|
const {ipcRenderer, webFrame} = require('electron')
|
||||||
|
webFrame.setZoomLevel(0.6)
|
||||||
|
ipcRenderer.send('zoom-level-set', webFrame.getZoomLevel())
|
||||||
|
`
|
||||||
|
const zoomLevelPromise = emittedOnce(ipcMain, 'zoom-level-set')
|
||||||
|
await w.loadURL(serverUrl)
|
||||||
|
await w.webContents.executeJavaScript(source)
|
||||||
|
let [, zoomLevel] = await zoomLevelPromise
|
||||||
expect(zoomLevel).to.equal(0.6)
|
expect(zoomLevel).to.equal(0.6)
|
||||||
w.loadFile(path.join(fixturesPath, 'pages', 'd.html'))
|
const loadPromise = emittedOnce(w.webContents, 'did-finish-load')
|
||||||
initialNavigation = false
|
await w.loadURL(crossSiteUrl)
|
||||||
|
await loadPromise
|
||||||
|
zoomLevel = w.webContents.zoomLevel
|
||||||
|
expect(zoomLevel).to.equal(0)
|
||||||
})
|
})
|
||||||
w.loadFile(path.join(fixturesPath, 'pages', 'c.html'))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1077,7 +1092,7 @@ describe('webContents module', () => {
|
||||||
const w = new BrowserWindow({ show: false })
|
const w = new BrowserWindow({ show: false })
|
||||||
let rvhDeletedCount = 0
|
let rvhDeletedCount = 0
|
||||||
w.webContents.once('destroyed', () => {
|
w.webContents.once('destroyed', () => {
|
||||||
const expectedRenderViewDeletedEventCount = 3 // 1 speculative upon redirection + 2 upon window close.
|
const expectedRenderViewDeletedEventCount = 1
|
||||||
expect(rvhDeletedCount).to.equal(expectedRenderViewDeletedEventCount, 'render-view-deleted wasn\'t emitted the expected nr. of times')
|
expect(rvhDeletedCount).to.equal(expectedRenderViewDeletedEventCount, 'render-view-deleted wasn\'t emitted the expected nr. of times')
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue