Merge pull request #9389 from electron/fix-remote-exception-sandbox

Keep track of remote object reference count.
This commit is contained in:
Cheng Zhao 2017-05-17 16:20:26 +09:00 committed by GitHub
commit 6826595e9e
7 changed files with 106 additions and 5 deletions

View file

@ -394,6 +394,11 @@ ipcMain.on('ELECTRON_BROWSER_DEREFERENCE', function (event, id) {
objectsRegistry.remove(event.sender.getId(), id) objectsRegistry.remove(event.sender.getId(), id)
}) })
ipcMain.on('ELECTRON_BROWSER_CONTEXT_RELEASE', (e) => {
objectsRegistry.clear(e.sender.getId())
e.returnValue = null
})
ipcMain.on('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', function (event, guestInstanceId) { ipcMain.on('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', function (event, guestInstanceId) {
try { try {
let guestViewManager = require('./guest-view-manager') let guestViewManager = require('./guest-view-manager')

View file

@ -304,6 +304,10 @@ ipcRenderer.on('ELECTRON_RENDERER_RELEASE_CALLBACK', function (event, id) {
callbacksRegistry.remove(id) callbacksRegistry.remove(id)
}) })
process.on('exit', () => {
ipcRenderer.sendSync('ELECTRON_BROWSER_CONTEXT_RELEASE')
})
// Get remote module. // Get remote module.
exports.require = function (module) { exports.require = function (module) {
return metaToValue(ipcRenderer.sendSync('ELECTRON_BROWSER_REQUIRE', module)) return metaToValue(ipcRenderer.sendSync('ELECTRON_BROWSER_REQUIRE', module))

View file

@ -1161,7 +1161,6 @@ describe('BrowserWindow module', function () {
} }
}) })
w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?allocate-memory')) w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?allocate-memory'))
w.webContents.openDevTools({mode: 'detach'})
ipcMain.once('answer', function (event, {bytesBeforeOpen, bytesAfterOpen, bytesAfterClose}) { ipcMain.once('answer', function (event, {bytesBeforeOpen, bytesAfterOpen, bytesAfterClose}) {
const memoryIncreaseByOpen = bytesAfterOpen - bytesBeforeOpen const memoryIncreaseByOpen = bytesAfterOpen - bytesBeforeOpen
const memoryDecreaseByClose = bytesAfterOpen - bytesAfterClose const memoryDecreaseByClose = bytesAfterOpen - bytesAfterClose
@ -1173,6 +1172,73 @@ describe('BrowserWindow module', function () {
done() done()
}) })
}) })
// see #9387
it('properly manages remote object references after page reload', (done) => {
w.destroy()
w = new BrowserWindow({
show: false,
webPreferences: {
preload: preload,
sandbox: true
}
})
w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?reload-remote'))
ipcMain.on('get-remote-module-path', (event) => {
event.returnValue = path.join(fixtures, 'module', 'hello.js')
})
let reload = false
ipcMain.on('reloaded', (event) => {
event.returnValue = reload
reload = !reload
})
ipcMain.once('reload', (event) => {
event.sender.reload()
})
ipcMain.once('answer', (event, arg) => {
ipcMain.removeAllListeners('reloaded')
ipcMain.removeAllListeners('get-remote-module-path')
assert.equal(arg, 'hi')
done()
})
})
it('properly manages remote object references after page reload in child window', (done) => {
w.destroy()
w = new BrowserWindow({
show: false,
webPreferences: {
preload: preload,
sandbox: true
}
})
w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?reload-remote-child'))
ipcMain.on('get-remote-module-path', (event) => {
event.returnValue = path.join(fixtures, 'module', 'hello-child.js')
})
let reload = false
ipcMain.on('reloaded', (event) => {
event.returnValue = reload
reload = !reload
})
ipcMain.once('reload', (event) => {
event.sender.reload()
})
ipcMain.once('answer', (event, arg) => {
ipcMain.removeAllListeners('reloaded')
ipcMain.removeAllListeners('get-remote-module-path')
assert.equal(arg, 'hi child window')
done()
})
})
}) })
describe('nativeWindowOpen option', () => { describe('nativeWindowOpen option', () => {

View file

@ -13,13 +13,28 @@
await timeout(100) await timeout(100)
} }
} }
if (window.opener) {
const [,test] = window.location.href.split('?')
if (window.opener && test !== 'reload-remote') {
window.callback = () => { window.callback = () => {
opener.require('electron').ipcRenderer.send('answer', document.body.innerHTML) opener.require('electron').ipcRenderer.send('answer', document.body.innerHTML)
} }
} else { } else {
const {ipcRenderer} = require('electron') const {ipcRenderer, remote} = require('electron')
const tests = { const tests = {
'reload-remote-child': () => {
open(`${location.protocol}//${location.pathname}?reload-remote`)
},
'reload-remote': async () => {
const p = ipcRenderer.sendSync('get-remote-module-path')
const Hello = remote.require(p)
if (!ipcRenderer.sendSync('reloaded')) {
ipcRenderer.send('reload')
return
}
await invokeGc()
ipcRenderer.send('answer', new Hello().say())
},
'allocate-memory': async () => { 'allocate-memory': async () => {
await invokeGc() await invokeGc()
const {privateBytes: bytesBeforeOpen} = process.getProcessMemoryInfo() const {privateBytes: bytesBeforeOpen} = process.getProcessMemoryInfo()
@ -95,7 +110,6 @@
popup.close() popup.close()
}, false) }, false)
let [,test] = window.location.href.split('?')
if (tests.hasOwnProperty(test)) if (tests.hasOwnProperty(test))
tests[test]() tests[test]()
} }

6
spec/fixtures/module/hello-child.js vendored Normal file
View file

@ -0,0 +1,6 @@
class Hello {
say () {
return 'hi child window'
}
}
module.exports = Hello

6
spec/fixtures/module/hello.js vendored Normal file
View file

@ -0,0 +1,6 @@
class Hello {
say () {
return 'hi'
}
}
module.exports = Hello

View file

@ -3,9 +3,9 @@
const {ipcRenderer} = require('electron') const {ipcRenderer} = require('electron')
window.ipcRenderer = ipcRenderer window.ipcRenderer = ipcRenderer
window.setImmediate = setImmediate window.setImmediate = setImmediate
window.require = require
if (location.protocol === 'file:') { if (location.protocol === 'file:') {
window.test = 'preload' window.test = 'preload'
window.require = require
window.process = process window.process = process
} else if (location.href !== 'about:blank') { } else if (location.href !== 'about:blank') {
addEventListener('DOMContentLoaded', () => { addEventListener('DOMContentLoaded', () => {