Bug 1879820 - Consume user activation when submitting form opens a new window; r=smaug,zcorpan
Differential Revision: https://phabricator.services.mozilla.com/D228648
This commit is contained in:
@@ -6767,9 +6767,18 @@ nsresult nsGlobalWindowOuter::OpenInternal(
|
|||||||
// (indirectly) maybe we can nix the AutoJSAPI usage OnLinkClickEvent::Run.
|
// (indirectly) maybe we can nix the AutoJSAPI usage OnLinkClickEvent::Run.
|
||||||
// But note that if you change this to GetEntryGlobal(), say, then
|
// But note that if you change this to GetEntryGlobal(), say, then
|
||||||
// OnLinkClickEvent::Run will need a full-blown AutoEntryScript. (Bug 1930445)
|
// OnLinkClickEvent::Run will need a full-blown AutoEntryScript. (Bug 1930445)
|
||||||
const bool checkForPopup =
|
const bool checkForPopup = [&]() {
|
||||||
!nsContentUtils::LegacyIsCallerChromeOrNativeCode() && !aDialog &&
|
if (aDialog) {
|
||||||
!windowExists;
|
return false;
|
||||||
|
}
|
||||||
|
if (windowExists) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (aLoadState && aLoadState->IsFormSubmission()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !nsContentUtils::LegacyIsCallerChromeOrNativeCode();
|
||||||
|
}();
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsCOMPtr<nsIURI> uri;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ prefs = ["formhelper.autozoom.force-disable.test-only=true"]
|
|||||||
|
|
||||||
["test_popup_blocker_async_callback.html"]
|
["test_popup_blocker_async_callback.html"]
|
||||||
|
|
||||||
|
["test_popup_blocker_form_target_blank.html"]
|
||||||
|
support-files = ["file_self_close.html"]
|
||||||
|
|
||||||
["test_popup_blocker_link_target_blank.html"]
|
["test_popup_blocker_link_target_blank.html"]
|
||||||
support-files = ["file_self_close.html"]
|
support-files = ["file_self_close.html"]
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for triggering the popup blocker by submitting a target=_blank form</title>
|
||||||
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form action="file_self_close.html" target="_blank"><button>Submit</button></form>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
let { ContentTaskUtils } = SpecialPowers.ChromeUtils.importESModule(
|
||||||
|
"resource://testing-common/ContentTaskUtils.sys.mjs"
|
||||||
|
);
|
||||||
|
|
||||||
|
function testTargetBlankForm(aSubmitFun, aMsg) {
|
||||||
|
add_task(async () => {
|
||||||
|
info(aMsg);
|
||||||
|
let popupBlockedPromise = ContentTaskUtils.waitForEvent(document, "DOMPopupBlocked", false, () => {
|
||||||
|
ok(true, "received DOMPopupBlocked event");
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
let form = document.querySelector("form");
|
||||||
|
form.addEventListener("submit", () => {
|
||||||
|
// Consume the user activation to ensure the popup is blocked.
|
||||||
|
SpecialPowers.wrap(document).clearUserGestureActivation();
|
||||||
|
});
|
||||||
|
aSubmitFun();
|
||||||
|
await popupBlockedPromise;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add_setup(async function() {
|
||||||
|
await SpecialPowers.pushPrefEnv({"set": [
|
||||||
|
// Enbale popup blocker
|
||||||
|
["dom.disable_open_during_load", true],
|
||||||
|
]});
|
||||||
|
});
|
||||||
|
|
||||||
|
testTargetBlankForm(() => {
|
||||||
|
synthesizeMouseAtCenter(document.querySelector("button"), {});
|
||||||
|
}, "Submit form by clicking submit button");
|
||||||
|
|
||||||
|
testTargetBlankForm(() => {
|
||||||
|
// Bug 1930678, form.submit() throws an error when the popup is blocked.
|
||||||
|
try {
|
||||||
|
document.querySelector("form").submit();
|
||||||
|
} catch(e) {}
|
||||||
|
}, "Submit form by submit()");
|
||||||
|
|
||||||
|
testTargetBlankForm(() => {
|
||||||
|
document.querySelector("form").requestSubmit();
|
||||||
|
}, "Submit form by requestSubmit()");
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# XXX(edgar): Need to enable popup blocker due to bug 1930458.
|
||||||
|
prefs: [dom.disable_open_during_load:true]
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# XXX(edgar): Need to enable popup blocker due to bug 1930458.
|
||||||
|
prefs: [dom.disable_open_during_load:true]
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Multi-globals: which userActivation should be consumed when submitting a target=_blank form?</title>
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/#concept-form-submit">
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/#the-rules-for-choosing-a-navigable">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="/resources/testdriver.js"></script>
|
||||||
|
<script src="/resources/testdriver-vendor.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function waitForNewWindow(aChannelName) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let channel = new BroadcastChannel(aChannelName);
|
||||||
|
channel.addEventListener("message", () => {
|
||||||
|
assert_true(true, "new window is opened");
|
||||||
|
resolve(channel);
|
||||||
|
}, {once: true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFormSubmission(aChannelName, aSubmitFun, aMsg) {
|
||||||
|
promise_test(async (t) => {
|
||||||
|
await test_driver.bless('active main test window to open popup test window');
|
||||||
|
let popupPromise = waitForNewWindow("popup");
|
||||||
|
let popup = window.open("resources/endpoint.html?channelname=popup");
|
||||||
|
t.add_cleanup(() => { popup.close(); });
|
||||||
|
await popupPromise;
|
||||||
|
|
||||||
|
popup.document.documentElement.innerHTML += `
|
||||||
|
<form action=endpoint.html target=_blank>
|
||||||
|
<input type=hidden name=channelname value=${aChannelName}>
|
||||||
|
</form>
|
||||||
|
`;
|
||||||
|
|
||||||
|
await test_driver.bless('active main test window again');
|
||||||
|
assert_true(navigator.userActivation.isActive, 'main test window should have user activation');
|
||||||
|
|
||||||
|
await test_driver.bless('active popup test window', () => {}, popup);
|
||||||
|
assert_true(popup.navigator.userActivation.isActive, 'popup test window should have user activation');
|
||||||
|
|
||||||
|
let newWindowPromise = waitForNewWindow(aChannelName);
|
||||||
|
aSubmitFun(popup.document.querySelector("form"));
|
||||||
|
let newWindowChannel = await newWindowPromise;
|
||||||
|
t.add_cleanup(() => { newWindowChannel.postMessage("close"); });
|
||||||
|
|
||||||
|
assert_true(navigator.userActivation.isActive, 'main test window should still have user activation');
|
||||||
|
assert_false(popup.navigator.userActivation.isActive, 'popup test window should not have user activation');
|
||||||
|
}, aMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
testFormSubmission(`${Date.now()}_script_submit`, (form) => {
|
||||||
|
form.submit();
|
||||||
|
}, `<form target=_blank>.submit()`);
|
||||||
|
|
||||||
|
testFormSubmission(`${Date.now()}_script_requestSubmit`, (form) => {
|
||||||
|
form.requestSubmit();
|
||||||
|
}, `<form target=_blank>.requestSubmit()`);
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Test that submitting a target=_blank form consumes userActivation</title>
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/#concept-form-submit">
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/#the-rules-for-choosing-a-navigable">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="/resources/testdriver.js"></script>
|
||||||
|
<script src="/resources/testdriver-vendor.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<form action=resources/endpoint.html target=_blank>
|
||||||
|
<input type=hidden name=channelname>
|
||||||
|
<button>Submit</button>
|
||||||
|
</form>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function waitForNewWindow(aChannelName) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let channel = new BroadcastChannel(aChannelName);
|
||||||
|
channel.addEventListener("message", () => {
|
||||||
|
assert_true(true, "new window is opened");
|
||||||
|
channel.postMessage("close");
|
||||||
|
resolve();
|
||||||
|
}, {once: true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testFormSubmission(aChannelName, aSubmitFun, aMsg) {
|
||||||
|
promise_test(async () => {
|
||||||
|
document.querySelector("input").value = aChannelName;
|
||||||
|
|
||||||
|
await test_driver.bless('transient activation');
|
||||||
|
assert_true(navigator.userActivation.isActive, 'should have user activation');
|
||||||
|
|
||||||
|
let newWindowPromise = waitForNewWindow(aChannelName);
|
||||||
|
aSubmitFun();
|
||||||
|
await newWindowPromise;
|
||||||
|
assert_false(navigator.userActivation.isActive, 'navigator.userActivation.isActive after opening a new window');
|
||||||
|
}, aMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
testFormSubmission(`${Date.now()}_script_submit`, () => {
|
||||||
|
document.querySelector("form").submit();
|
||||||
|
}, `<form target=_blank>.submit()`);
|
||||||
|
|
||||||
|
testFormSubmission(`${Date.now()}_script_requestSubmit`, () => {
|
||||||
|
document.querySelector("form").requestSubmit();
|
||||||
|
}, `<form target=_blank>.requestSubmit()`);
|
||||||
|
|
||||||
|
testFormSubmission(`${Date.now()}_click_submit`, () => {
|
||||||
|
test_driver.click(document.querySelector("button"));
|
||||||
|
}, `<form target=_blank> click submit`);
|
||||||
|
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user