fix: remove memory leak when using webFrame and spell checker (#16770)

* fix: do not create native api::WebFrame in webFrame

When reloading a page without restarting renderer process (for example
sandbox mode), the blink::WebFrame is not destroyed, but api::WebFrame
is always recreated for the new page context. This leaves a leak of
api::WebFrame.

* fix: remove spell checker when page context is released
This commit is contained in:
Cheng Zhao 2019-02-09 06:38:31 +09:00 committed by Samuel Attard
parent 3f52e18a38
commit d16b581140
5 changed files with 354 additions and 348 deletions

View file

@ -1,13 +1,67 @@
'use strict'
const { EventEmitter } = require('events')
const { webFrame, WebFrame } = process.atomBinding('web_frame')
const binding = process.atomBinding('web_frame')
// WebFrame is an EventEmitter.
Object.setPrototypeOf(WebFrame.prototype, EventEmitter.prototype)
EventEmitter.call(webFrame)
class WebFrame extends EventEmitter {
constructor (context) {
super()
// Lots of webview would subscribe to webFrame's events.
webFrame.setMaxListeners(0)
this.context = context
// Lots of webview would subscribe to webFrame's events.
this.setMaxListeners(0)
}
module.exports = webFrame
findFrameByRoutingId (...args) {
return getWebFrame(binding._findFrameByRoutingId(this.context, ...args))
}
getFrameForSelector (...args) {
return getWebFrame(binding._getFrameForSelector(this.context, ...args))
}
findFrameByName (...args) {
return getWebFrame(binding._findFrameByName(this.context, ...args))
}
get opener () {
return getWebFrame(binding._getOpener(this.context))
}
get parent () {
return getWebFrame(binding._getParent(this.context))
}
get top () {
return getWebFrame(binding._getTop(this.context))
}
get firstChild () {
return getWebFrame(binding._getFirstChild(this.context))
}
get nextSibling () {
return getWebFrame(binding._getNextSibling(this.context))
}
get routingId () {
return binding._getRoutingId(this.context)
}
}
// Populate the methods.
for (const name in binding) {
if (!name.startsWith('_')) { // some methods are manully populated above
WebFrame.prototype[name] = function (...args) {
return binding[name](this.context, ...args)
}
}
}
// Helper to return WebFrame or null depending on context.
// TODO(zcbenz): Consider returning same WebFrame for the same frame.
function getWebFrame (context) {
return context ? new WebFrame(context) : null
}
module.exports = new WebFrame(window)