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`.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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) {
 | 
				
			||||||
 | 
					    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.`)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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', () => {
 | 
				
			||||||
 | 
					      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()
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue