diff options
Diffstat (limited to '')
-rw-r--r-- | docshell/test/browser/browser_bug422543.js | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/docshell/test/browser/browser_bug422543.js b/docshell/test/browser/browser_bug422543.js new file mode 100644 index 0000000000..d3b772619e --- /dev/null +++ b/docshell/test/browser/browser_bug422543.js @@ -0,0 +1,253 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const ACTOR = "Bug422543"; + +let getActor = browser => { + return browser.browsingContext.currentWindowGlobal.getActor(ACTOR); +}; + +add_task(async function runTests() { + if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) { + await setupAsync(); + let browser = gBrowser.selectedBrowser; + // Now that we're set up, initialize our frame script. + await checkListenersAsync("initial", "listeners initialized"); + + // Check if all history listeners are always notified. + info("# part 1"); + await whenPageShown(browser, () => + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + BrowserTestUtils.loadURIString(browser, "http://www.example.com/") + ); + await checkListenersAsync("newentry", "shistory has a new entry"); + ok(browser.canGoBack, "we can go back"); + + await whenPageShown(browser, () => browser.goBack()); + await checkListenersAsync("gotoindex", "back to the first shentry"); + ok(browser.canGoForward, "we can go forward"); + + await whenPageShown(browser, () => browser.goForward()); + await checkListenersAsync("gotoindex", "forward to the second shentry"); + + await whenPageShown(browser, () => browser.reload()); + await checkListenersAsync("reload", "current shentry reloaded"); + + await whenPageShown(browser, () => browser.gotoIndex(0)); + await checkListenersAsync("gotoindex", "back to the first index"); + + // Check nsISHistory.notifyOnHistoryReload + info("# part 2"); + ok(await notifyReloadAsync(), "reloading has not been canceled"); + await checkListenersAsync("reload", "saw the reload notification"); + + // Let the first listener cancel the reload action. + info("# part 3"); + await resetListenersAsync(); + await setListenerRetvalAsync(0, false); + ok(!(await notifyReloadAsync()), "reloading has been canceled"); + await checkListenersAsync("reload", "saw the reload notification"); + + // Let both listeners cancel the reload action. + info("# part 4"); + await resetListenersAsync(); + await setListenerRetvalAsync(1, false); + ok(!(await notifyReloadAsync()), "reloading has been canceled"); + await checkListenersAsync("reload", "saw the reload notification"); + + // Let the second listener cancel the reload action. + info("# part 5"); + await resetListenersAsync(); + await setListenerRetvalAsync(0, true); + ok(!(await notifyReloadAsync()), "reloading has been canceled"); + await checkListenersAsync("reload", "saw the reload notification"); + + function sendQuery(message, arg = {}) { + return getActor(gBrowser.selectedBrowser).sendQuery(message, arg); + } + + function checkListenersAsync(aLast, aMessage) { + return sendQuery("getListenerStatus").then(listenerStatuses => { + is(listenerStatuses[0], aLast, aMessage); + is(listenerStatuses[1], aLast, aMessage); + }); + } + + function resetListenersAsync() { + return sendQuery("resetListeners"); + } + + function notifyReloadAsync() { + return sendQuery("notifyReload").then(({ rval }) => { + return rval; + }); + } + + function setListenerRetvalAsync(num, val) { + return sendQuery("setRetval", { num, val }); + } + + async function setupAsync() { + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "http://mochi.test:8888" + ); + + let base = getRootDirectory(gTestPath).slice(0, -1); + ChromeUtils.registerWindowActor(ACTOR, { + child: { + esModuleURI: `${base}/Bug422543Child.sys.mjs`, + }, + }); + + registerCleanupFunction(async () => { + await sendQuery("cleanup"); + gBrowser.removeTab(tab); + + ChromeUtils.unregisterWindowActor(ACTOR); + }); + + await sendQuery("init"); + } + return; + } + + await setup(); + let browser = gBrowser.selectedBrowser; + // Now that we're set up, initialize our frame script. + checkListeners("initial", "listeners initialized"); + + // Check if all history listeners are always notified. + info("# part 1"); + await whenPageShown(browser, () => + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + BrowserTestUtils.loadURIString(browser, "http://www.example.com/") + ); + checkListeners("newentry", "shistory has a new entry"); + ok(browser.canGoBack, "we can go back"); + + await whenPageShown(browser, () => browser.goBack()); + checkListeners("gotoindex", "back to the first shentry"); + ok(browser.canGoForward, "we can go forward"); + + await whenPageShown(browser, () => browser.goForward()); + checkListeners("gotoindex", "forward to the second shentry"); + + await whenPageShown(browser, () => browser.reload()); + checkListeners("reload", "current shentry reloaded"); + + await whenPageShown(browser, () => browser.gotoIndex(0)); + checkListeners("gotoindex", "back to the first index"); + + // Check nsISHistory.notifyOnHistoryReload + info("# part 2"); + ok(notifyReload(browser), "reloading has not been canceled"); + checkListeners("reload", "saw the reload notification"); + + // Let the first listener cancel the reload action. + info("# part 3"); + resetListeners(); + setListenerRetval(0, false); + ok(!notifyReload(browser), "reloading has been canceled"); + checkListeners("reload", "saw the reload notification"); + + // Let both listeners cancel the reload action. + info("# part 4"); + resetListeners(); + setListenerRetval(1, false); + ok(!notifyReload(browser), "reloading has been canceled"); + checkListeners("reload", "saw the reload notification"); + + // Let the second listener cancel the reload action. + info("# part 5"); + resetListeners(); + setListenerRetval(0, true); + ok(!notifyReload(browser), "reloading has been canceled"); + checkListeners("reload", "saw the reload notification"); +}); + +class SHistoryListener { + constructor() { + this.retval = true; + this.last = "initial"; + } + + OnHistoryNewEntry(aNewURI) { + this.last = "newentry"; + } + + OnHistoryGotoIndex() { + this.last = "gotoindex"; + } + + OnHistoryPurge() { + this.last = "purge"; + } + + OnHistoryReload() { + this.last = "reload"; + return this.retval; + } + + OnHistoryReplaceEntry() {} +} +SHistoryListener.prototype.QueryInterface = ChromeUtils.generateQI([ + "nsISHistoryListener", + "nsISupportsWeakReference", +]); + +let listeners = [new SHistoryListener(), new SHistoryListener()]; + +function checkListeners(aLast, aMessage) { + is(listeners[0].last, aLast, aMessage); + is(listeners[1].last, aLast, aMessage); +} + +function resetListeners() { + for (let listener of listeners) { + listener.last = "initial"; + } +} + +function notifyReload(browser) { + return browser.browsingContext.sessionHistory.notifyOnHistoryReload(); +} + +function setListenerRetval(num, val) { + listeners[num].retval = val; +} + +async function setup() { + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "http://mochi.test:8888" + ); + + let browser = tab.linkedBrowser; + registerCleanupFunction(async function () { + for (let listener of listeners) { + browser.browsingContext.sessionHistory.removeSHistoryListener(listener); + } + gBrowser.removeTab(tab); + }); + for (let listener of listeners) { + browser.browsingContext.sessionHistory.addSHistoryListener(listener); + } +} + +function whenPageShown(aBrowser, aNavigation) { + let promise = new Promise(resolve => { + let unregister = BrowserTestUtils.addContentEventListener( + aBrowser, + "pageshow", + () => { + unregister(); + resolve(); + }, + { capture: true } + ); + }); + + aNavigation(); + return promise; +} |