Skip to content

Commit

Permalink
Change navigable target names to _blank if they have dangling markup
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=257349

Reviewed by Chris Dumez.

whatwg/html#9309

* LayoutTests/imported/w3c/resources/import-expectations.json:
* LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/dangling-markup-window-name.tentative-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/dangling-markup-window-name.tentative.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/resources/window-name.sub.html:
* LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/w3c-import.log:
* LayoutTests/tests-options.json:
* Source/WebCore/dom/Element.cpp:
(WebCore::Element::makeTargetBlankIfHasDanglingMarkup const):
* Source/WebCore/dom/Element.h:
* Source/WebCore/html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::effectiveTarget const):
* Source/WebCore/html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::effectiveTarget const):

Canonical link: https://commits.webkit.org/267154@main
  • Loading branch information
sideshowbarker authored and Ahmad Saleem committed Aug 22, 2023
1 parent b2fab9c commit 6752480
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@
"web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.sub.html": "skip",
"web-platform-tests/html/browsers/sandboxing": "skip",
"web-platform-tests/html/browsers/the-window-object": "import",
"web-platform-tests/html/browsers/windows": "import",
"web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts": "import",
"web-platform-tests/html/browsers/windows/browsing-context-first-created.xhtml": "skip",
"web-platform-tests/html/browsers/windows/browsing-context-names": "import",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

PASS Dangling Markup in target is not reset when set by window.open
PASS Dangling Markup with "\n" in target is reset when set by <a> tag
PASS Dangling Markup with "\r" in target is reset when set by <a> tag
PASS Dangling Markup with "\t" in target is reset when set by <a> tag
PASS Dangling Markup in target is reset when set by <form> tag
PASS Dangling Markup in target is reset when set by <base> tag

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<!doctype html>
<html>
<head>
<title>Dangling Markup in target</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/utils.js"></script>
</head>
<body>
<script>
function anchorClick(target, id) {
const hyperlink = document.body.appendChild(document.createElement('a'));
if (target) {
hyperlink.target = target;
}
hyperlink.href = `resources/window-name.sub.html?report=${id}|close`;
hyperlink.click();
}

async function pollResultAndCheck(t, id, expected) {
const stashURL = new URL('resources/window-name-stash.py', location);
stashURL.searchParams.set('id', id);

let res = 'NONE';
while (res == 'NONE') {
await new Promise(resolve => { t.step_timeout(resolve, 100); });

const response = await fetch(stashURL);
res = await response.text();
}
if (res !== expected) {
assert_unreached('Stash result does not equal expected result.')
}
}

promise_test(async t => {
const id = token();
const value = '\n<' + id;

window.open(`resources/window-name.sub.html?report=${id}|close`, value);
await pollResultAndCheck(t, id, value);
}, 'Dangling Markup in target is not reset when set by window.open');

promise_test(async t => {
const id = token();
const value = '\n<' + id;

anchorClick(value, id)
await pollResultAndCheck(t, id, '');
}, 'Dangling Markup with "\\n" in target is reset when set by <a> tag');

promise_test(async t => {
const id = token();
const value = '\r<' + id;

anchorClick(value, id)
await pollResultAndCheck(t, id, '');
}, 'Dangling Markup with "\\r" in target is reset when set by <a> tag');

promise_test(async t => {
const id = token();
const value = '\t<' + id;

anchorClick(value, id)
await pollResultAndCheck(t, id, '');
}, 'Dangling Markup with "\\t" in target is reset when set by <a> tag');

promise_test(async t => {
const id = token();
const value = '\n<' + id;

const form = document.body.appendChild(document.createElement('form'));
form.target = value;
form.method = 'GET';
form.action = 'resources/window-name.sub.html';
const input = form.appendChild(document.createElement('input'));
input.type = 'hidden';
input.name = 'report';
input.value = `${id}|close`;
form.submit();

await pollResultAndCheck(t, id, '');
}, 'Dangling Markup in target is reset when set by <form> tag');

promise_test(async t => {
const id = token();
const value = '\n<' + id;
const base = document.head.appendChild(document.createElement('base'));
base.target = value;

anchorClick(null, id)
await pollResultAndCheck(t, id, '');
}, 'Dangling Markup in target is reset when set by <base> tag');
</script>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<title>popup helper</title>
<script>

const search = window.location.search.replace("?", "");
const search = decodeURIComponent(window.location.search.replace("?", ""));
const steps = search.split("|");

async function proceedTest() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ List of files:
/LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/browsing-context-window.html
/LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/browsing-context.html
/LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/clear-window-name.https.html
/LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/dangling-markup-window-name.tentative.html
/LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/document-domain-nested-navigate.window.js
/LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/document-domain-nested-set.window.js
/LayoutTests/imported/w3c/web-platform-tests/html/browsers/windows/document-domain-nested.window.js
Expand Down
3 changes: 3 additions & 0 deletions LayoutTests/tests-options.json
Original file line number Diff line number Diff line change
Expand Up @@ -3383,6 +3383,9 @@
"imported/w3c/web-platform-tests/html/browsers/windows/clear-window-name.https.html": [
"slow"
],
"imported/w3c/web-platform-tests/html/browsers/windows/dangling-markup-window-name.tentative.html": [
"slow"
],
"imported/w3c/web-platform-tests/html/browsers/windows/noreferrer-window-name.html": [
"slow"
],
Expand Down
7 changes: 7 additions & 0 deletions Source/WebCore/dom/Element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5399,4 +5399,11 @@ void Element::contentVisibilityViewportChange(bool)
document().scheduleContentRelevancyUpdate(ContentRelevancy::OnScreen);
}

AtomString Element::makeTargetBlankIfHasDanglingMarkup(const AtomString& target)
{
if ((target.contains('\n') || target.contains('\r') || target.contains('\t')) && target.contains('<'))
return "_blank"_s;
return target;
}

} // namespace WebCore
2 changes: 2 additions & 0 deletions Source/WebCore/dom/Element.h
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,8 @@ class Element : public ContainerNode {

void updateLabel(TreeScope&, const AtomString& oldForAttributeValue, const AtomString& newForAttributeValue);

static AtomString makeTargetBlankIfHasDanglingMarkup(const AtomString& target);

private:
LocalFrame* documentFrameWithNonNullView() const;
void hideNonceSlow();
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/html/HTMLAnchorElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ AtomString HTMLAnchorElement::effectiveTarget() const
auto effectiveTarget = target();
if (effectiveTarget.isEmpty())
effectiveTarget = document().baseTarget();
return effectiveTarget;
return makeTargetBlankIfHasDanglingMarkup(effectiveTarget);
}

HTMLAnchorElement::EventType HTMLAnchorElement::eventType(Event& event)
Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/html/HTMLFormElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,12 +735,12 @@ AtomString HTMLFormElement::effectiveTarget(const Event* event, HTMLFormControlE
if (RefPtr submitter = overrideSubmitter ? overrideSubmitter : findSubmitter(event)) {
auto& targetValue = submitter->attributeWithoutSynchronization(formtargetAttr);
if (!targetValue.isNull())
return targetValue;
return makeTargetBlankIfHasDanglingMarkup(targetValue);
}

auto targetValue = target();
if (!targetValue.isNull())
return targetValue;
return makeTargetBlankIfHasDanglingMarkup(targetValue);

return document().baseTarget();
}
Expand Down

0 comments on commit 6752480

Please sign in to comment.