Bug 1411393 - Marionette should not register listeners on the global window or document. r=ato,smaug

Registering listeners for the "beforeunload" and "unload" events currently
happens on the global window and document. This actually prevents Firefox
from adding those pages to the bfcache.

The correct is to add all the listeners to the tabchildglobal, which is
the framescript itself. Also by using the capture and not the bubble phase
the unload events are correctly propagaded to our registered listeners.

MozReview-Commit-ID: 4hJjuqWsoBP

--HG--
extra : rebase_source : 619a8c936f613823dab2387efa67dc65488fbbc3
This commit is contained in:
Henrik Skupin 2017-10-25 14:15:30 +02:00
parent ea1a8597fe
commit 20ad958852

View File

@ -133,14 +133,11 @@ const loadListener = {
} }
if (waitForUnloaded) { if (waitForUnloaded) {
addEventListener("hashchange", this, false); addEventListener("beforeunload", this, true);
addEventListener("pagehide", this, false); addEventListener("hashchange", this, true);
addEventListener("popstate", this, false); addEventListener("pagehide", this, true);
addEventListener("popstate", this, true);
// The events can only be received when the event listeners are addEventListener("unload", this, true);
// added to the currently selected frame.
curContainer.frame.addEventListener("beforeunload", this);
curContainer.frame.addEventListener("unload", this);
Services.obs.addObserver(this, "outer-window-destroyed"); Services.obs.addObserver(this, "outer-window-destroyed");
@ -160,8 +157,8 @@ const loadListener = {
return; return;
} }
addEventListener("DOMContentLoaded", loadListener); addEventListener("DOMContentLoaded", loadListener, true);
addEventListener("pageshow", loadListener); addEventListener("pageshow", loadListener, true);
} }
this.timerPageLoad.initWithCallback( this.timerPageLoad.initWithCallback(
@ -180,22 +177,13 @@ const loadListener = {
this.timerPageUnload.cancel(); this.timerPageUnload.cancel();
} }
removeEventListener("hashchange", this); removeEventListener("beforeunload", this, true);
removeEventListener("pagehide", this); removeEventListener("hashchange", this, true);
removeEventListener("popstate", this); removeEventListener("pagehide", this, true);
removeEventListener("DOMContentLoaded", this); removeEventListener("popstate", this, true);
removeEventListener("pageshow", this); removeEventListener("DOMContentLoaded", this, true);
removeEventListener("pageshow", this, true);
// If the original content window, where the navigation was triggered, removeEventListener("unload", this, true);
// doesn't exist anymore, exceptions can be silently ignored.
try {
curContainer.frame.removeEventListener("beforeunload", this);
curContainer.frame.removeEventListener("unload", this);
} catch (e) {
if (e.name != "TypeError") {
throw e;
}
}
// In case the observer was added before the frame script has been // In case the observer was added before the frame script has been
// reloaded, it will no longer be available. Exceptions can be ignored. // reloaded, it will no longer be available. Exceptions can be ignored.
@ -230,13 +218,13 @@ const loadListener = {
case "pagehide": case "pagehide":
this.seenUnload = true; this.seenUnload = true;
removeEventListener("hashchange", this); removeEventListener("hashchange", this, true);
removeEventListener("pagehide", this); removeEventListener("pagehide", this, true);
removeEventListener("popstate", this); removeEventListener("popstate", this, true);
// Now wait until the target page has been loaded // Now wait until the target page has been loaded
addEventListener("DOMContentLoaded", this, false); addEventListener("DOMContentLoaded", this, true);
addEventListener("pageshow", this, false); addEventListener("pageshow", this, true);
break; break;
case "hashchange": case "hashchange":