зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1700871 - Only allow focus move for links / form submission iff actually handling user input. r=smaug
The other navigation that allows focus moves (window.open) already goes through the popup blocker, so that one is fine. I think given how weird yet conservative other browsers are, this should be a good trade-off to avoid false positives. Differential Revision: https://phabricator.services.mozilla.com/D110196
This commit is contained in:
Родитель
2c09fd18ba
Коммит
168b2347b3
|
@ -12847,6 +12847,7 @@ nsresult nsDocShell::OnLinkClick(
|
|||
aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal());
|
||||
loadState->SetPrincipalToInherit(aContent->NodePrincipal());
|
||||
loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp());
|
||||
loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied,
|
||||
|
@ -13011,7 +13012,6 @@ nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
|||
aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));
|
||||
aLoadState->SetLoadType(loadType);
|
||||
aLoadState->SetSourceBrowsingContext(mBrowsingContext);
|
||||
aLoadState->SetAllowFocusMove(true);
|
||||
aLoadState->SetHasValidUserGestureActivation(
|
||||
context && context->HasValidTransientUserGestureActivation());
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ skip-if =
|
|||
os == 'win' && bits == 64 # Bug 1692963
|
||||
support-files =
|
||||
file_bug1691214.html
|
||||
file_bug1700871.html
|
||||
[browser_inputStream_structuredClone.js]
|
||||
[browser_multiple_popups.js]
|
||||
skip-if = (os == 'win' && !debug) || (os == "mac" && !debug) # Bug 1505235, Bug 1661132 (osx)
|
||||
|
|
|
@ -291,19 +291,13 @@ function clickLink(
|
|||
waitForLocationChange(targetsFrame, testBrowser, locationChangeNum)
|
||||
);
|
||||
}
|
||||
|
||||
info("BC children: " + browser.browsingContext.children.length);
|
||||
promises.push(
|
||||
SpecialPowers.spawn(
|
||||
browser,
|
||||
[[isFrame, linkId]],
|
||||
([contentIsFrame, contentLinkId]) => {
|
||||
let doc = content.document;
|
||||
if (contentIsFrame) {
|
||||
let frame = content.document.getElementById("frame");
|
||||
doc = frame.contentDocument;
|
||||
}
|
||||
info("Clicking " + contentLinkId);
|
||||
doc.querySelector(contentLinkId).click();
|
||||
}
|
||||
BrowserTestUtils.synthesizeMouseAtCenter(
|
||||
linkId,
|
||||
{},
|
||||
isFrame ? browser.browsingContext.children[0] : browser
|
||||
)
|
||||
);
|
||||
return Promise.all(promises);
|
||||
|
|
|
@ -6,25 +6,28 @@
|
|||
|
||||
const BASE_URL = "http://mochi.test:8888/browser/dom/base/test/";
|
||||
|
||||
add_task(async function() {
|
||||
async function newFocusedWindow() {
|
||||
let delayedStartupPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let win = await BrowserTestUtils.domWindowOpenedAndLoaded();
|
||||
// New windows get focused after the first paint, see bug 1262946
|
||||
await BrowserTestUtils.waitForContentEvent(
|
||||
win.gBrowser.selectedBrowser,
|
||||
"MozAfterPaint"
|
||||
);
|
||||
await delayedStartupPromise;
|
||||
return win;
|
||||
}
|
||||
|
||||
add_task(async function bug1691214() {
|
||||
await BrowserTestUtils.withNewTab(
|
||||
BASE_URL + "file_bug1691214.html",
|
||||
async function(browser) {
|
||||
let win;
|
||||
|
||||
{
|
||||
let newWindow = BrowserTestUtils.domWindowOpenedAndLoaded();
|
||||
let delayedStartupPromise = BrowserTestUtils.waitForNewWindow();
|
||||
|
||||
let newWindow = newFocusedWindow();
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("#link-1", {}, browser);
|
||||
win = await newWindow;
|
||||
ok(win, "First navigation should've opened the new window");
|
||||
// New windows get focused after the first paint, see bug 1262946
|
||||
await BrowserTestUtils.waitForContentEvent(
|
||||
win.gBrowser.selectedBrowser,
|
||||
"MozAfterPaint"
|
||||
);
|
||||
await delayedStartupPromise;
|
||||
is(Services.focus.focusedWindow, win, "New window should be focused");
|
||||
}
|
||||
|
||||
|
@ -56,3 +59,42 @@ add_task(async function() {
|
|||
}
|
||||
);
|
||||
});
|
||||
|
||||
// The tab has a form infinitely submitting to an iframe, and that shouldn't
|
||||
// switch focus back. For that, we open a window from the tab, make sure it's
|
||||
// focused, and then wait for three submissions (but since we need to listen to
|
||||
// trusted events from chrome code, we use the iframe load event instead).
|
||||
add_task(async function bug1700871() {
|
||||
await BrowserTestUtils.withNewTab(
|
||||
BASE_URL + "file_bug1700871.html",
|
||||
async function(browser) {
|
||||
let win;
|
||||
|
||||
{
|
||||
let newWindow = newFocusedWindow();
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("#link-1", {}, browser);
|
||||
win = await newWindow;
|
||||
is(Services.focus.focusedWindow, win, "New window should be focused");
|
||||
}
|
||||
|
||||
info("waiting for three submit events and ensuring focus hasn't moved");
|
||||
|
||||
await SpecialPowers.spawn(browser, [], function() {
|
||||
let pending = 3;
|
||||
return new Promise(resolve => {
|
||||
content.document
|
||||
.querySelector("iframe")
|
||||
.addEventListener("load", function(e) {
|
||||
info("Got load on the frame: " + pending);
|
||||
if (!--pending) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
is(Services.focus.focusedWindow, win, "Focus shouldn't have moved");
|
||||
win.close();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -6,20 +6,29 @@ Tests for tab switching on link clicks.
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for tab switching on link clicks.</title>
|
||||
<style>
|
||||
a {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
overflow: hidden;
|
||||
background-color: currentColor;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a id="link-1" target="testTab" href="file_bug1303838_target_foo.html">Link 1</a><br>
|
||||
<a id="link-2" target="testTab" href="file_bug1303838_target_bar.html">Link 2</a><br>
|
||||
<a id="link-3" target="testTab" href="file_bug1303838_target_baz.html">Link 3</a><br>
|
||||
<a id="link-4" href="#" onclick="testTab = window.open('file_bug1303838_target_foo.html', 'testTab'); return false;">Link 4</a><br>
|
||||
<a id="link-5" href="#" onclick="testTab.location.href += '?1'; return false;">Link 5</a><br>
|
||||
<a id="link-6" href="#" onclick="testTab.location.href += '#1'; return false;">Link 6</a><br>
|
||||
<a id="link-7" target="testTab" href="file_bug1303838_target.html">Link 7</a><br>
|
||||
<a id="anchor-link-1" target="testTab" href="file_bug1303838_target.html#foo">Anchor Link 1</a><br>
|
||||
<a id="anchor-link-2" target="testTab" href="file_bug1303838_target.html#bar">Anchor Link 2</a><br>
|
||||
<a id="anchor-link-3" target="testTab" href="file_bug1303838_target.html#baz">Anchor Link 3</a><br>
|
||||
<a id="frame-link-1" target="testFrame" href="file_bug1303838_target_ifoo.html">Frame Link 1</a><br>
|
||||
<a id="frame-link-2" target="testFrame" href="file_bug1303838_target_ibar.html">Frame Link 2</a><br>
|
||||
<a id="frame-link-3" target="testFrame" href="file_bug1303838_target_ibaz.html">Frame Link 3</a><br>
|
||||
<a id="link-1" target="testTab" href="file_bug1303838_target_foo.html">Link 1</a>,
|
||||
<a id="link-2" target="testTab" href="file_bug1303838_target_bar.html">Link 2</a>,
|
||||
<a id="link-3" target="testTab" href="file_bug1303838_target_baz.html">Link 3</a>,
|
||||
<a id="link-4" href="#" onclick="testTab = window.open('file_bug1303838_target_foo.html', 'testTab'); return false;">Link 4</a>,
|
||||
<a id="link-5" href="#" onclick="testTab.location.href += '?1'; return false;">Link 5</a>,
|
||||
<a id="link-6" href="#" onclick="testTab.location.href += '#1'; return false;">Link 6</a>,
|
||||
<a id="link-7" target="testTab" href="file_bug1303838_target.html">Link 7</a>,
|
||||
<a id="anchor-link-1" target="testTab" href="file_bug1303838_target.html#foo">Anchor Link 1</a>,
|
||||
<a id="anchor-link-2" target="testTab" href="file_bug1303838_target.html#bar">Anchor Link 2</a>,
|
||||
<a id="anchor-link-3" target="testTab" href="file_bug1303838_target.html#baz">Anchor Link 3</a>,
|
||||
<a id="frame-link-1" target="testFrame" href="file_bug1303838_target_ifoo.html">Frame Link 1</a>,
|
||||
<a id="frame-link-2" target="testFrame" href="file_bug1303838_target_ibar.html">Frame Link 2</a>,
|
||||
<a id="frame-link-3" target="testFrame" href="file_bug1303838_target_ibaz.html">Frame Link 3</a>,
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<a id="link-1" href="?1" onclick="window.open(this.href, 'childWin', 'height=300,width=600'); return false;">Open in window.</a>
|
||||
<form target="frame" method="get">
|
||||
<input type=hidden name=counter value=0>
|
||||
<iframe name="frame" href="file_bug1700871.html"></iframe>
|
||||
</form>
|
||||
<script>
|
||||
(function submitForm() {
|
||||
if (location.search) {
|
||||
return; // Don't fork-bomb ourselves.
|
||||
}
|
||||
|
||||
let counter = document.querySelector("input");
|
||||
counter.value = ++counter.value;
|
||||
document.querySelector("form").submit();
|
||||
setTimeout(submitForm, 500);
|
||||
}());
|
||||
</script>
|
|
@ -825,6 +825,7 @@ nsresult HTMLFormElement::SubmitSubmission(
|
|||
loadState->SetTriggeringPrincipal(NodePrincipal());
|
||||
loadState->SetPrincipalToInherit(NodePrincipal());
|
||||
loadState->SetCsp(GetCsp());
|
||||
loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
|
||||
|
||||
rv = nsDocShell::Cast(container)->OnLinkClickSync(this, loadState, false,
|
||||
NodePrincipal());
|
||||
|
|
Загрузка…
Ссылка в новой задаче