summaryrefslogtreecommitdiffstats
path: root/browser/actors/test
diff options
context:
space:
mode:
Diffstat (limited to 'browser/actors/test')
-rw-r--r--browser/actors/test/browser/browser.ini4
-rw-r--r--browser/actors/test/browser/browser_nested_link_clicks.js45
-rw-r--r--browser/actors/test/browser/browser_untrusted_click_event.js107
-rw-r--r--browser/actors/test/browser/click.html76
4 files changed, 232 insertions, 0 deletions
diff --git a/browser/actors/test/browser/browser.ini b/browser/actors/test/browser/browser.ini
new file mode 100644
index 0000000000..586e4962e8
--- /dev/null
+++ b/browser/actors/test/browser/browser.ini
@@ -0,0 +1,4 @@
+[browser_nested_link_clicks.js]
+[browser_untrusted_click_event.js]
+support-files =
+ click.html
diff --git a/browser/actors/test/browser/browser_nested_link_clicks.js b/browser/actors/test/browser/browser_nested_link_clicks.js
new file mode 100644
index 0000000000..32ac6a4685
--- /dev/null
+++ b/browser/actors/test/browser/browser_nested_link_clicks.js
@@ -0,0 +1,45 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Nested links should only open a single tab when ctrl-clicked.
+ */
+add_task(async function nested_link_click_opens_single_tab() {
+ await BrowserTestUtils.withNewTab(
+ "https://example.com/empty",
+ async browser => {
+ await SpecialPowers.spawn(browser, [], () => {
+ let doc = content.document;
+ let outerLink = doc.createElement("a");
+ outerLink.href = "https://mozilla.org/";
+ let link = doc.createElement("a");
+ link.href = "https://example.org/linked";
+ link.textContent = "Click me";
+ link.id = "mylink";
+ outerLink.append(link);
+ doc.body.append(outerLink);
+ });
+
+ let startingNumberOfTabs = gBrowser.tabs.length;
+ let newTabPromise = BrowserTestUtils.waitForNewTab(
+ gBrowser,
+ "https://example.org/linked",
+ true
+ );
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#mylink",
+ { accelKey: true },
+ browser
+ );
+ let tab = await newTabPromise;
+ is(
+ gBrowser.tabs.length,
+ startingNumberOfTabs + 1,
+ "Should only have opened 1 tab."
+ );
+ BrowserTestUtils.removeTab(tab);
+ }
+ );
+});
diff --git a/browser/actors/test/browser/browser_untrusted_click_event.js b/browser/actors/test/browser/browser_untrusted_click_event.js
new file mode 100644
index 0000000000..7bb579223d
--- /dev/null
+++ b/browser/actors/test/browser/browser_untrusted_click_event.js
@@ -0,0 +1,107 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_PATH = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "https://example.com"
+);
+
+/**
+ * Ensure that click handlers that prevent the default action but fire
+ * a different click event that does open a tab are allowed to work.
+ */
+add_task(async function test_untrusted_click_opens_tab() {
+ await BrowserTestUtils.withNewTab(TEST_PATH + "click.html", async browser => {
+ let newTabOpened = BrowserTestUtils.waitForNewTab(
+ gBrowser,
+ "https://example.org/",
+ true
+ );
+ info("clicking link with modifier pressed.");
+ let eventObj = {};
+ eventObj[AppConstants.platform == "macosx" ? "metaKey" : "ctrlKey"] = true;
+ await BrowserTestUtils.synthesizeMouseAtCenter("#test", eventObj, browser);
+ info(
+ "Waiting for new tab to open from frontend; if we timeout the test is broken."
+ );
+ let newTab = await newTabOpened;
+ ok(newTab, "New tab should be opened.");
+ BrowserTestUtils.removeTab(newTab);
+ });
+});
+
+/**
+ * Ensure that click handlers that redirect a modifier-less click into
+ * an untrusted event without modifiers don't run afoul of the popup
+ * blocker by having their transient user gesture bit consumed in the
+ * child by the handling code for modified clicks.
+ */
+add_task(async function test_unused_click_doesnt_consume_activation() {
+ // Enable the popup blocker.
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.disable_open_during_load", true],
+ ["dom.block_multiple_popups", true],
+ ],
+ });
+ await BrowserTestUtils.withNewTab(TEST_PATH + "click.html", async browser => {
+ let newTabOpened = BrowserTestUtils.waitForNewTab(
+ gBrowser,
+ "https://example.com/",
+ true
+ );
+ info("clicking button that generates link press.");
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#fire-untrusted",
+ {},
+ browser
+ );
+ info(
+ "Waiting for new tab to open through gecko; if we timeout the test is broken."
+ );
+ let newTab = await newTabOpened;
+ ok(newTab, "New tab should be opened.");
+ BrowserTestUtils.removeTab(newTab);
+ });
+});
+
+/**
+ * Ensure that click handlers redirecting to elements without href don't
+ * trigger user gesture consumption either.
+ */
+add_task(async function test_click_without_href_doesnt_consume_activation() {
+ // Enable the popup blocker.
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.disable_open_during_load", true],
+ ["dom.block_multiple_popups", true],
+ ],
+ });
+ await BrowserTestUtils.withNewTab(TEST_PATH + "click.html", async browser => {
+ let newTabOpened = BrowserTestUtils.waitForNewTab(gBrowser, "about:blank");
+ info("clicking link that generates link click on target-less link.");
+ await BrowserTestUtils.synthesizeMouseAtCenter(
+ "#fire-targetless-link",
+ {},
+ browser
+ );
+ info(
+ "Waiting for new tab to open after targetless link; if we timeout the test is broken."
+ );
+ let newTab = await newTabOpened;
+ ok(newTab, "New tab should be opened.");
+ BrowserTestUtils.removeTab(newTab);
+
+ newTabOpened = BrowserTestUtils.waitForNewTab(gBrowser, "about:blank");
+ info("clicking link that generates button click.");
+ await BrowserTestUtils.synthesizeMouseAtCenter("#fire-button", {}, browser);
+ info(
+ "Waiting for new tab to open after button redirect; if we timeout the test is broken."
+ );
+ newTab = await newTabOpened;
+ ok(newTab, "New tab should be opened.");
+ BrowserTestUtils.removeTab(newTab);
+ });
+});
diff --git a/browser/actors/test/browser/click.html b/browser/actors/test/browser/click.html
new file mode 100644
index 0000000000..42afdf8050
--- /dev/null
+++ b/browser/actors/test/browser/click.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Click a link whose event we intercept</title>
+</head>
+<body>
+
+<a id="test" href="https://example.com/">click me</a><br><br>
+
+<a id="untrusted-only" href="https://example.com/" target="_blank">This is a link, works only with untrusted events</a><br>
+<input id="fire-untrusted" type=button value="Click me to trigger an untrusted event"><br><br>
+
+<a id="fire-targetless-link" href="unused">Click me (dispatch untrusted event to link without href)</a><br>
+<a id="fire-button" href="unused">Click me (dispatch untrusted event to button)</a>
+
+<script>
+
+ document.getElementById("test").addEventListener("click", originalClick => {
+ const newLink = document.createElement("a");
+ newLink.setAttribute("rel", "noreferrer");
+ newLink.setAttribute("target", "_blank");
+ newLink.setAttribute("href", "https://example.org/");
+
+
+ document.body.appendChild(newLink);
+
+ const evt = document.createEvent('MouseEvent');
+ evt.initMouseEvent(
+ "click", true, true, window, 0,
+ originalClick.screenX, originalClick.screenY, originalClick.clientX, originalClick.clientY,
+ originalClick.ctrlKey, originalClick.altKey, originalClick.shiftKey, originalClick.metaKey,
+ originalClick.button, originalClick.relatedTarget
+ );
+ newLink.dispatchEvent(evt);
+
+
+ originalClick.preventDefault();
+ originalClick.stopPropagation();
+ });
+
+ document.getElementById("untrusted-only").addEventListener("click", ev => {
+ if (ev.isTrusted) {
+ ev.preventDefault();
+ }
+ });
+
+ document.getElementById("fire-untrusted").addEventListener("click", () => {
+ document.getElementById("untrusted-only").dispatchEvent(new MouseEvent("click"));
+ });
+
+ function handleTargetless(e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ const buttonOrLink = e.target.id.includes("button") ? "button" : "a";
+ const newElement = document.createElement(buttonOrLink);
+ document.body.appendChild(newElement);
+
+ const evt = document.createEvent("MouseEvent");
+ evt.initMouseEvent("click", true, true, window, 0, e.screenX, e.screenY,
+ e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey,
+ e.metaKey, e.button, e.relatedTarget);
+ newElement.dispatchEvent(evt);
+ newElement.remove();
+
+ setTimeout(() => {
+ window.open();
+ }, 0);
+ }
+ document.getElementById("fire-targetless-link").addEventListener("click", handleTargetless);
+ document.getElementById("fire-button").addEventListener("click", handleTargetless);
+
+</script>
+</body>
+</html>