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:
Samuel Attard 2020-02-24 18:11:06 -08:00 committed by GitHub
parent 7a91078cc7
commit 7b7def7d1e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 146 additions and 103 deletions

View file

@ -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`.

View file

@ -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.

View file

@ -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) {
if (status) {
const textStatus = process.platform === 'win32' ? `0x${status.toString(16)}` : status.toString() const textStatus = process.platform === 'win32' ? `0x${status.toString(16)}` : status.toString()
console.log(`${fail} Electron tests failed with code ${textStatus}.`) 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.`)

View file

@ -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.

View file

@ -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 () => {

View file

@ -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,

View file

@ -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 = [

View file

@ -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
} }

View file

@ -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', () => {
let server: http.Server
let serverUrl: string
let crossSiteUrl: string
before((done) => {
server = http.createServer((req, res) => {
setTimeout(() => res.end('hey'), 0)
})
server.listen(0, '127.0.0.1', () => {
serverUrl = `http://127.0.0.1:${(server.address() as AddressInfo).port}`
crossSiteUrl = `http://localhost:${(server.address() as AddressInfo).port}`
done()
})
})
after(() => {
server.close()
})
it('cannot persist zoom level after navigation with webFrame', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } }) const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } })
let initialNavigation = true
const source = ` const source = `
const {ipcRenderer, webFrame} = require('electron') const {ipcRenderer, webFrame} = require('electron')
webFrame.setZoomLevel(0.6) webFrame.setZoomLevel(0.6)
ipcRenderer.send('zoom-level-set', webFrame.getZoomLevel()) ipcRenderer.send('zoom-level-set', webFrame.getZoomLevel())
` `
w.webContents.on('did-finish-load', () => { const zoomLevelPromise = emittedOnce(ipcMain, 'zoom-level-set')
if (initialNavigation) { await w.loadURL(serverUrl)
w.webContents.executeJavaScript(source) await w.webContents.executeJavaScript(source)
} else { let [, zoomLevel] = await zoomLevelPromise
const zoomLevel = w.webContents.zoomLevel
expect(zoomLevel).to.equal(0)
done()
}
})
ipcMain.once('zoom-level-set', (e, zoomLevel) => {
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()
}) })