зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1222516 part 4. Implement support for rel=noopener on links. r=mconley
This commit is contained in:
Родитель
d53cc929eb
Коммит
34454ebcd3
|
@ -13963,11 +13963,16 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
|||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
|
||||
nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(referrer);
|
||||
while (tok.hasMoreTokens()) {
|
||||
if (tok.nextToken().LowerCaseEqualsLiteral("noreferrer")) {
|
||||
const nsAString& token = tok.nextToken();
|
||||
if (token.LowerCaseEqualsLiteral("noreferrer")) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
|
||||
INTERNAL_LOAD_FLAGS_NO_OPENER;
|
||||
// We now have all the flags we could possibly have, so just stop.
|
||||
break;
|
||||
}
|
||||
if (token.LowerCaseEqualsLiteral("noopener")) {
|
||||
flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
|
|||
// static
|
||||
const DOMTokenListSupportedToken HTMLAnchorElement::sSupportedRelValues[] = {
|
||||
"noreferrer",
|
||||
"noopener",
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
|
|
@ -37660,6 +37660,12 @@
|
|||
"url": "/html/semantics/forms/the-textarea-element/cloning-steps.html"
|
||||
}
|
||||
],
|
||||
"html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html": [
|
||||
{
|
||||
"path": "html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html",
|
||||
"url": "/html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html"
|
||||
}
|
||||
],
|
||||
"html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html": [
|
||||
{
|
||||
"path": "html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html",
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test behavior of rel="noopener" links</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<iframe name="oursubframe"></iframe>
|
||||
<a href="support/noopener-target-2.html" rel="noopener" target="ourpopup"></a>
|
||||
<a href="support/noopener-target-2.html" rel="noopener" target="oursubframe"></a>
|
||||
<script>
|
||||
var tests = [];
|
||||
// First test the special targets
|
||||
function target1Loaded(win) {
|
||||
// Find the relevant test
|
||||
var test = tests.find((t) => t.openedWindow == win);
|
||||
test.step(function() {
|
||||
assert_equals(win.opener, window);
|
||||
win.close();
|
||||
test.done();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Test that <a rel="noopener"> targeted at one of _self, _parent, _top does the
|
||||
* load in the appropriate existing browsing context instead of opening a new
|
||||
* one. The test is run in a separate popup window we open and which we can
|
||||
* navigate without causing the test harness going into conniptions.
|
||||
*/
|
||||
for (var target of ["self", "parent", "top"]) {
|
||||
var t = async_test("Check that rel=noopener with target=_" + target + " does a normal load");
|
||||
tests.push(t);
|
||||
t.openedWindow = window.open("support/noopener-popup.html");
|
||||
t.targetName = target;
|
||||
t.openedWindow.onload = t.step_func(function() {
|
||||
this.openedWindow.findLink(this.targetName).click();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* And now check that a noopener load targeted at something other than one of
|
||||
* the three special targets above in fact ignores existing things with the
|
||||
* given name. We do this in two ways. First, by opening a window named
|
||||
* "ourpopup" and then doing a load via <a rel="noopener" target="ourpopup"> and
|
||||
* verifying that the load happens in a window with a null opener, etc, while
|
||||
* the opener of the thing we opened is not modified. And second, by targeting
|
||||
* <a rel="noopener"> at a name that an existing subframe has, and ensuring that
|
||||
* this subframe is not navigated.
|
||||
*/
|
||||
var t1 = async_test("Check that targeting of rel=noopener with a given name ignores an existing window with that name");
|
||||
var w;
|
||||
t1.add_cleanup(function() { w.close(); });
|
||||
var channel = new BroadcastChannel("ourpopup");
|
||||
channel.onmessage = t1.step_func_done(function(e) {
|
||||
var data = e.data;
|
||||
assert_false(data.hasOpener);
|
||||
assert_false(data.hasParent);
|
||||
assert_equals(data.name, "ourpopup");
|
||||
assert_equals(w.opener, window);
|
||||
assert_equals(w.location.href, "about:blank");
|
||||
});
|
||||
t1.step(function() {
|
||||
w = window.open("", "ourpopup");
|
||||
assert_equals(w.opener, window);
|
||||
document.querySelectorAll("a")[0].click();
|
||||
});
|
||||
|
||||
var t2 = async_test("Check that targeting of rel=noopener with a given name ignores an existing subframe with that name");
|
||||
var channel = new BroadcastChannel("oursubframe");
|
||||
channel.onmessage = t2.step_func_done(function(e) {
|
||||
var data = e.data;
|
||||
assert_false(data.hasOpener);
|
||||
assert_false(data.hasParent);
|
||||
assert_equals(data.name, "oursubframe");
|
||||
assert_equals(document.querySelector("iframe").contentWindow.location.href,
|
||||
"about:blank");
|
||||
});
|
||||
t2.step(function() {
|
||||
document.querySelectorAll("a")[1].click();
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<script>
|
||||
function findLink(arg) {
|
||||
var doc;
|
||||
if (arg == "self") {
|
||||
doc = document;
|
||||
} else {
|
||||
doc = frames[0].document;
|
||||
}
|
||||
return doc.getElementById(arg + "target");
|
||||
}
|
||||
</script>
|
||||
<a rel="noopener" target="_self" id="selftarget"
|
||||
href="noopener-target-1.html"></a>
|
||||
<iframe srcdoc='
|
||||
<a rel="noopener" target="_parent" id="parenttarget"
|
||||
href="noopener-target-1.html"></a>
|
||||
<a rel="noopener" target="_top" id="toptarget"
|
||||
href="noopener-target-1.html"></a>'></iframe>
|
|
@ -0,0 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<script>
|
||||
opener.target1Loaded(this);
|
||||
</script>
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<script>
|
||||
var channel = new BroadcastChannel(this.name);
|
||||
channel.postMessage({ hasOpener: opener !== null ,
|
||||
hasParent: parent != this,
|
||||
name: window.name });
|
||||
window.close();
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче