зеркало из https://github.com/mozilla/gecko-dev.git
Bug 899354 - Only ever add one visibilitychange listener to BrowserElementParent's owner window. r=khuey
This prevents a leak when we run tests that create thousands of BrowserElementParents without ever turning the screen off.
This commit is contained in:
Родитель
429cdd568c
Коммит
2847abff91
|
@ -67,13 +67,22 @@ function defineAndExpose(obj, name, value) {
|
|||
obj.__exposedProps__[name] = 'r';
|
||||
}
|
||||
|
||||
function visibilityChangeHandler(weakBEP, win) {
|
||||
let bep = weakBEP.get();
|
||||
if (bep) {
|
||||
bep._ownerVisibilityChange();
|
||||
} else {
|
||||
win.removeEventListener('visibilitychange', visibilityChangeHandler,
|
||||
/* useCapture */ false);
|
||||
function visibilityChangeHandler(e) {
|
||||
// The visibilitychange event's target is the document.
|
||||
let win = e.target.defaultView;
|
||||
|
||||
if (!win._browserElementParents) {
|
||||
return;
|
||||
}
|
||||
|
||||
let beps = Cu.nondeterministicGetWeakMapKeys(win._browserElementParents);
|
||||
if (beps.length == 0) {
|
||||
win.removeEventListener('visibilitychange', visibilityChangeHandler);
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < beps.length; i++) {
|
||||
beps[i]._ownerVisibilityChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,15 +187,25 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) {
|
|||
defineDOMRequestMethod('getCanGoBack', 'get-can-go-back');
|
||||
defineDOMRequestMethod('getCanGoForward', 'get-can-go-forward');
|
||||
|
||||
// Listen to visibilitychange on the iframe's owner window, and forward it
|
||||
// down to the child. The event listener must hold a weak reference to this,
|
||||
// otherwise the window will hold this object alive.
|
||||
// Listen to visibilitychange on the iframe's owner window, and forward
|
||||
// changes down to the child. We want to do this while registering as few
|
||||
// visibilitychange listeners on _window as possible, because such a listener
|
||||
// may live longer than this BrowserElementParent object.
|
||||
//
|
||||
// To accomplish this, we register just one listener on the window, and have
|
||||
// it reference a WeakMap whose keys are all the BrowserElementParent objects
|
||||
// on the window. Then when the listener fires, we iterate over the
|
||||
// WeakMap's keys (which we can do, because we're chrome) to notify the
|
||||
// BrowserElementParents.
|
||||
if (!this._window._browserElementParents) {
|
||||
this._window._browserElementParents = new WeakMap();
|
||||
this._window.addEventListener('visibilitychange',
|
||||
visibilityChangeHandler,
|
||||
/* useCapture = */ false,
|
||||
/* wantsUntrusted = */ false);
|
||||
}
|
||||
|
||||
var weakSelf = Cu.getWeakReference(this);
|
||||
this._window.addEventListener('visibilitychange',
|
||||
visibilityChangeHandler.bind(null, weakSelf, this._window),
|
||||
/* useCapture = */ false,
|
||||
/* wantsUntrusted = */ false);
|
||||
this._window._browserElementParents.set(this, null);
|
||||
|
||||
// Insert ourself into the prompt service.
|
||||
BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this);
|
||||
|
|
Загрузка…
Ссылка в новой задаче