Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"use strict";
const TEST_PAGE =
getRootDirectory(gTestPath).replace(
) + "dummy_page.html";
const IFRAME_PAGE =
getRootDirectory(gTestPath).replace(
) + "dummy_iframe_page.html";
async function assertMenulist(entries, baseURL = TEST_PAGE) {
// Wait for the session data to be flushed before continuing the test
await new Promise(resolve =>
SessionStore.getSessionHistory(gBrowser.selectedTab, resolve)
);
let backButton = document.getElementById("back-button");
let contextMenu = document.getElementById("backForwardMenu");
info("waiting for the history menu to open");
let popupShownPromise = BrowserTestUtils.waitForEvent(
contextMenu,
"popupshown"
);
EventUtils.synthesizeMouseAtCenter(backButton, {
type: "contextmenu",
button: 2,
});
await popupShownPromise;
ok(true, "history menu opened");
let nodes = contextMenu.childNodes;
is(
nodes.length,
entries.length,
"Has the expected number of contextMenu entries"
);
for (let i = 0; i < entries.length; i++) {
let node = nodes[i];
is(
node.getAttribute("uri").replace(/[?|#]/, "!"),
baseURL + "!entry=" + entries[i],
"contextMenu node has the correct uri"
);
}
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
contextMenu,
"popuphidden"
);
contextMenu.hidePopup();
await popupHiddenPromise;
}
// There are different ways of loading a page, but they should exhibit roughly the same
// back-forward behavior for the purpose of requiring user interaction. Thus, we
// have a utility function that runs the same test with a parameterized method of loading
// new URLs.
async function runTopLevelTest(loadMethod, useHashes = false) {
let p = useHashes ? "#" : "?";
// Test with both pref on and off
for (let requireUserInteraction of [true, false]) {
Services.prefs.setBoolPref(
"browser.navigation.requireUserInteraction",
requireUserInteraction
);
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_PAGE + p + "entry=0"
);
let browser = tab.linkedBrowser;
assertBackForwardState(false, false);
await loadMethod(TEST_PAGE + p + "entry=1");
assertBackForwardState(true, false);
await assertMenulist([1, 0]);
await loadMethod(TEST_PAGE + p + "entry=2");
assertBackForwardState(true, false);
await assertMenulist(requireUserInteraction ? [2, 0] : [2, 1, 0]);
await loadMethod(TEST_PAGE + p + "entry=3");
info("Adding user interaction for entry=3");
// Add some user interaction to entry 3
await BrowserTestUtils.synthesizeMouse(
"body",
0,
0,
{},
browser.browsingContext,
true
);
assertBackForwardState(true, false);
await assertMenulist(requireUserInteraction ? [3, 0] : [3, 2, 1, 0]);
await loadMethod(TEST_PAGE + p + "entry=4");
assertBackForwardState(true, false);
await assertMenulist(requireUserInteraction ? [4, 3, 0] : [4, 3, 2, 1, 0]);
info("Adding user interaction for entry=4");
// Add some user interaction to entry 4
await BrowserTestUtils.synthesizeMouse(
"body",
0,
0,
{},
browser.browsingContext,
true
);
await loadMethod(TEST_PAGE + p + "entry=5");
assertBackForwardState(true, false);
await assertMenulist(
requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0]
);
await goBack(TEST_PAGE + p + "entry=4");
await goBack(TEST_PAGE + p + "entry=3");
if (!requireUserInteraction) {
await goBack(TEST_PAGE + p + "entry=2");
await goBack(TEST_PAGE + p + "entry=1");
}
assertBackForwardState(true, true);
await assertMenulist(
requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0]
);
await goBack(TEST_PAGE + p + "entry=0");
assertBackForwardState(false, true);
if (!requireUserInteraction) {
await goForward(TEST_PAGE + p + "entry=1");
await goForward(TEST_PAGE + p + "entry=2");
}
await goForward(TEST_PAGE + p + "entry=3");
assertBackForwardState(true, true);
await assertMenulist(
requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0]
);
await goForward(TEST_PAGE + p + "entry=4");
assertBackForwardState(true, true);
await assertMenulist(
requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0]
);
await goForward(TEST_PAGE + p + "entry=5");
assertBackForwardState(true, false);
await assertMenulist(
requireUserInteraction ? [5, 4, 3, 0] : [5, 4, 3, 2, 1, 0]
);
BrowserTestUtils.removeTab(tab);
}
Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
}
async function runIframeTest(loadMethod) {
// Test with both pref on and off
for (let requireUserInteraction of [true, false]) {
Services.prefs.setBoolPref(
"browser.navigation.requireUserInteraction",
requireUserInteraction
);
// First test the boring case where we only have one iframe.
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
IFRAME_PAGE + "?entry=0"
);
let browser = tab.linkedBrowser;
assertBackForwardState(false, false);
await loadMethod(TEST_PAGE + "?sub_entry=1", "frame1");
assertBackForwardState(true, false);
await assertMenulist([0, 0], IFRAME_PAGE);
await loadMethod(TEST_PAGE + "?sub_entry=2", "frame1");
assertBackForwardState(true, false);
await assertMenulist(
requireUserInteraction ? [0, 0] : [0, 0, 0],
IFRAME_PAGE
);
let bc = await SpecialPowers.spawn(browser, [], function () {
return content.document.getElementById("frame1").browsingContext;
});
// Add some user interaction to sub entry 2
await BrowserTestUtils.synthesizeMouse("body", 0, 0, {}, bc, true);
await loadMethod(TEST_PAGE + "?sub_entry=3", "frame1");
assertBackForwardState(true, false);
await assertMenulist(
requireUserInteraction ? [0, 0, 0] : [0, 0, 0, 0],
IFRAME_PAGE
);
await loadMethod(TEST_PAGE + "?sub_entry=4", "frame1");
assertBackForwardState(true, false);
await assertMenulist(
requireUserInteraction ? [0, 0, 0] : [0, 0, 0, 0, 0],
IFRAME_PAGE
);
if (!requireUserInteraction) {
await goBack(TEST_PAGE + "?sub_entry=3", true);
}
await goBack(TEST_PAGE + "?sub_entry=2", true);
assertBackForwardState(true, true);
await assertMenulist(
requireUserInteraction ? [0, 0, 0] : [0, 0, 0, 0, 0],
IFRAME_PAGE
);
await loadMethod(IFRAME_PAGE + "?entry=1");
assertBackForwardState(true, false);
await assertMenulist(
requireUserInteraction ? [1, 0, 0] : [1, 0, 0, 0],
IFRAME_PAGE
);
BrowserTestUtils.removeTab(tab);
// Two iframes, now we're talking.
tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
IFRAME_PAGE + "?entry=0"
);
browser = tab.linkedBrowser;
await loadMethod(IFRAME_PAGE + "?entry=1");
assertBackForwardState(true, false);
await assertMenulist(requireUserInteraction ? [1, 0] : [1, 0], IFRAME_PAGE);
// Add some user interaction to frame 1.
bc = await SpecialPowers.spawn(browser, [], function () {
return content.document.getElementById("frame1").browsingContext;
});
await BrowserTestUtils.synthesizeMouse("body", 0, 0, {}, bc, true);
// Add some user interaction to frame 2.
bc = await SpecialPowers.spawn(browser, [], function () {
return content.document.getElementById("frame2").browsingContext;
});
await BrowserTestUtils.synthesizeMouse("body", 0, 0, {}, bc, true);
// Navigate frame 2.
await loadMethod(TEST_PAGE + "?sub_entry=1", "frame2");
assertBackForwardState(true, false);
await assertMenulist(
requireUserInteraction ? [1, 1, 0] : [1, 1, 0],
IFRAME_PAGE
);
// Add some user interaction to frame 1, again.
bc = await SpecialPowers.spawn(browser, [], function () {
return content.document.getElementById("frame1").browsingContext;
});
await BrowserTestUtils.synthesizeMouse("body", 0, 0, {}, bc, true);
// Navigate frame 2, again.
await loadMethod(TEST_PAGE + "?sub_entry=2", "frame2");
assertBackForwardState(true, false);
await assertMenulist(
requireUserInteraction ? [1, 1, 1, 0] : [1, 1, 1, 0],
IFRAME_PAGE
);
await goBack(TEST_PAGE + "?sub_entry=1", true);
assertBackForwardState(true, true);
await assertMenulist(
requireUserInteraction ? [1, 1, 1, 0] : [1, 1, 1, 0],
IFRAME_PAGE
);
await goBack(TEST_PAGE + "?sub_entry=0", true);
assertBackForwardState(true, true);
await assertMenulist(
requireUserInteraction ? [1, 1, 1, 0] : [1, 1, 1, 0],
IFRAME_PAGE
);
BrowserTestUtils.removeTab(tab);
}
Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
}
// Test that when the pref is flipped, we are skipping history
// entries without user interaction when following links with hash URIs.
add_task(async function test_hashURI() {
async function followLinkHash(url) {
info(`Creating and following a link to ${url}`);
let browser = gBrowser.selectedBrowser;
let loaded = BrowserTestUtils.waitForLocationChange(gBrowser, url);
await SpecialPowers.spawn(browser, [url], function (url) {
let a = content.document.createElement("a");
a.href = url;
content.document.body.appendChild(a);
a.click();
});
await loaded;
info(`Loaded ${url}`);
}
await runTopLevelTest(followLinkHash, true);
});
// Test that when the pref is flipped, we are skipping history
// entries without user interaction when using history.pushState.
add_task(async function test_pushState() {
await runTopLevelTest(pushState);
});
// Test that when the pref is flipped, we are skipping history
// entries without user interaction when following a link.
add_task(async function test_followLink() {
await runTopLevelTest(followLink);
});
// Test that when the pref is flipped, we are skipping history
// entries without user interaction when navigating inside an iframe
// using history.pushState.
add_task(async function test_iframe_pushState() {
await runIframeTest(pushState);
});
// Test that when the pref is flipped, we are skipping history
// entries without user interaction when navigating inside an iframe
// by following links.
add_task(async function test_iframe_followLink() {
await runIframeTest(followLink);
});