Bug 1672660 - [devtools] Unregister docshell listeners only if we had time to register them. r=nchevobbe

It looks like we are destroying the target actor immediately, without having time
to call _watchDocshells. And given that removeObserver throws if there is no matching listener
already registered, it prevent detaching the target correctly, and, introduces a leak.

Differential Revision: https://phabricator.services.mozilla.com/D94452
This commit is contained in:
Alexandre Poirot 2020-10-22 20:13:28 +00:00
Родитель de552b9596
Коммит 8458fea935
1 изменённых файлов: 28 добавлений и 9 удалений

Просмотреть файл

@ -690,6 +690,8 @@ const browsingContextTargetPrototype = {
// Save references to the original document we attached to
this._originalWindow = this.window;
this._docShellsObserved = false;
// Ensure replying to attach() request first
// before notifying about new docshells.
DevToolsUtils.executeSoon(() => this._watchDocshells());
@ -698,9 +700,16 @@ const browsingContextTargetPrototype = {
},
_watchDocshells() {
// If for some unexpected reason, the actor is immediately destroyed,
// avoid registering leaking observer listener.
if (this.exited) {
return;
}
// In child processes, we watch all docshells living in the process.
Services.obs.addObserver(this, "webnavigation-create");
Services.obs.addObserver(this, "webnavigation-destroy");
this._docShellsObserved = true;
// We watch for all child docshells under the current document,
this._progressListener.watch(this.docShell);
@ -709,6 +718,24 @@ const browsingContextTargetPrototype = {
this._updateChildDocShells();
},
_unwatchDocshells() {
if (this._progressListener) {
this._progressListener.destroy();
this._progressListener = null;
this._originalWindow = null;
}
// Removes the observers being set in _watchDocshells, but only
// if _watchDocshells has been called. The target actor may be immediately destroyed
// and doesn't have time to register them.
// (Calling removeObserver without having called addObserver throws)
if (this._docShellsObserved) {
Services.obs.removeObserver(this, "webnavigation-create");
Services.obs.removeObserver(this, "webnavigation-destroy");
this._docShellsObserved = true;
}
},
_unwatchDocShell(docShell) {
if (this._progressListener) {
this._progressListener.unwatch(docShell);
@ -1033,15 +1060,7 @@ const browsingContextTargetPrototype = {
this._unwatchDocShell(this.docShell);
this._restoreDocumentSettings();
}
if (this._progressListener) {
this._progressListener.destroy();
this._progressListener = null;
this._originalWindow = null;
// Removes the observers being set in _watchDocShells
Services.obs.removeObserver(this, "webnavigation-create");
Services.obs.removeObserver(this, "webnavigation-destroy");
}
this._unwatchDocshells();
this._destroyThreadActor();