Bug 1323982 - Remove web progress listener once sawLoad is seen; r=whimboo

The web progress `onStateChange` callback sometimes gets called multiple
times.

To ensure we do not end up removing the web progress listener multiple
times, causing an exception to be thrown if it has already been
removed, we remove the listener as part of the cleanup step when the
DOMContentLoaded event listener is removed.

MozReview-Commit-ID: Lm3sfjohyLR

--HG--
extra : rebase_source : ba63fe8af685f1dc88e62f01108e284f1b96bbe6
This commit is contained in:
Andreas Tolfsen 2016-12-16 14:07:05 +00:00
Родитель 73a9a94cfd
Коммит 3ea2cb4d67
1 изменённых файлов: 14 добавлений и 15 удалений

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

@ -902,7 +902,7 @@ function pollForReadyState(msg, start = undefined, callback = undefined) {
callback = () => {}; callback = () => {};
} }
let checkLoad = function() { let checkLoad = () => {
navTimer.cancel(); navTimer.cancel();
let doc = curContainer.frame.document; let doc = curContainer.frame.document;
@ -1020,42 +1020,41 @@ function get(msg) {
// Prevent DOMContentLoaded events from frames from invoking this // Prevent DOMContentLoaded events from frames from invoking this
// code, unless the event is coming from the frame associated with // code, unless the event is coming from the frame associated with
// the current window (i.e. someone has used switch_to_frame). // the current window (i.e. someone has used switch_to_frame).
onDOMContentLoaded = function onDOMContentLoaded(event) { onDOMContentLoaded = ev => {
let frameEl = event.originalTarget.defaultView.frameElement; let frameEl = ev.originalTarget.defaultView.frameElement;
let correctFrame = !frameEl || frameEl == curContainer.frame.frameElement; let correctFrame = !frameEl || frameEl == curContainer.frame.frameElement;
// If the page we're at fired DOMContentLoaded and appears // If the page we're at fired DOMContentLoaded and appears to
// to be the one we asked to load, then we definitely // be the one we asked to load, then we definitely saw the load
// saw the load occur. We need this because for error // occur. We need this because for error pages, like about:neterror
// pages, like about:neterror for unsupported protocols, // for unsupported protocols, we don't end up opening a channel that
// we don't end up opening a channel that our // our WebProgressListener can monitor.
// WebProgressListener can monitor.
if (curContainer.frame.location == requestedURL) { if (curContainer.frame.location == requestedURL) {
sawLoad = true; sawLoad = true;
} }
// We also need to make sure that if the requested URL is not about:blank // We also need to make sure that if the requested URL is not
// the DOMContentLoaded we saw isn't for the initial about:blank of a newly // about:blank the DOMContentLoaded we saw isn't for the initial
// created docShell. // about:blank of a newly created docShell.
let loadedRequestedURI = (requestedURL == "about:blank") || let loadedRequestedURI = (requestedURL == "about:blank") ||
docShell.hasLoadedNonBlankURI; docShell.hasLoadedNonBlankURI;
if (correctFrame && sawLoad && loadedRequestedURI) { if (correctFrame && sawLoad && loadedRequestedURI) {
webProgress.removeProgressListener(loadListener);
pollForReadyState(msg, start, () => { pollForReadyState(msg, start, () => {
webProgress.removeProgressListener(loadListener);
removeEventListener("DOMContentLoaded", onDOMContentLoaded, false); removeEventListener("DOMContentLoaded", onDOMContentLoaded, false);
}); });
} }
}; };
if (typeof pageTimeout != "undefined") { if (typeof pageTimeout != "undefined") {
let onTimeout = function() { let onTimeout = () => {
if (loadEventExpected) { if (loadEventExpected) {
removeEventListener("DOMContentLoaded", onDOMContentLoaded, false); removeEventListener("DOMContentLoaded", onDOMContentLoaded, false);
} }
webProgress.removeProgressListener(loadListener); webProgress.removeProgressListener(loadListener);
sendError(new TimeoutError("Error loading page, timed out (onDOMContentLoaded)"), command_id); sendError(new TimeoutError("Error loading page, timed out (onDOMContentLoaded)"), command_id);
} };
navTimer.initWithCallback(onTimeout, pageTimeout, Ci.nsITimer.TYPE_ONE_SHOT); navTimer.initWithCallback(onTimeout, pageTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
} }