Bug 530396 - don't send a Referer header for rel="noreferrer" links; r=smaug

This commit is contained in:
Makoto Kato 2014-05-20 09:26:59 -04:00
parent b9757dfad4
commit 14f6f74d38
6 changed files with 119 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=4 sw=4 tw=80 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@ -29,6 +29,7 @@
#endif
#include "nsIContent.h"
#include "nsIContentInlines.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
@ -336,6 +337,18 @@ CheckPingURI(nsIURI* uri, nsIContent* content)
typedef void (* ForEachPingCallback)(void *closure, nsIContent *content,
nsIURI *uri, nsIIOService *ios);
static bool
IsElementAnchor(nsIContent* aContent)
{
// Make sure we are dealing with either an <A> or <AREA> element in the HTML
// or XHTML namespace.
if (!aContent->IsHTML()) {
return false;
}
nsIAtom* nameAtom = aContent->Tag();
return nameAtom == nsGkAtoms::a || nameAtom == nsGkAtoms::area;
}
static void
ForEachPing(nsIContent *content, ForEachPingCallback callback, void *closure)
{
@ -346,10 +359,7 @@ ForEachPing(nsIContent *content, ForEachPingCallback callback, void *closure)
// Make sure we are dealing with either an <A> or <AREA> element in the HTML
// or XHTML namespace.
if (!content->IsHTML())
return;
nsIAtom *nameAtom = content->Tag();
if (nameAtom != nsGkAtoms::a && nameAtom != nsGkAtoms::area)
if (!IsElementAnchor(content))
return;
nsCOMPtr<nsIAtom> pingAtom = do_GetAtom("ping");
@ -9080,6 +9090,11 @@ nsDocShell::InternalLoad(nsIURI * aURI,
if (!newDoc || newDoc->IsInitialDocument()) {
isNewWindow = true;
aFlags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
// set opener object to null for noreferrer
if (aFlags & INTERNAL_LOAD_FLAGS_NO_OPENER) {
piNewWin->SetOpenerWindow(nullptr, false);
}
}
}
@ -12634,6 +12649,18 @@ nsDocShell::OnLinkClickSync(nsIContent *aContent,
}
}
uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
if (IsElementAnchor(aContent)) {
MOZ_ASSERT(aContent->IsHTML());
if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::rel,
NS_LITERAL_STRING("noreferrer"),
aContent->IsInHTMLDocument() ?
eIgnoreCase : eCaseMatters)) {
flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
INTERNAL_LOAD_FLAGS_NO_OPENER;
}
}
// Get the owner document of the link that was clicked, this will be
// the document that the link is in, or the last document that the
// link was in. From that document, we'll get the URI to use as the
@ -12684,7 +12711,7 @@ nsDocShell::OnLinkClickSync(nsIContent *aContent,
referer, // Referer URI
aContent->NodePrincipal(), // Owner is our node's
// principal
INTERNAL_LOAD_FLAGS_NONE,
flags,
target.get(), // Window target
NS_LossyConvertUTF16toASCII(typeHint).get(),
aFileName, // Download as file

View File

@ -114,6 +114,7 @@ interface nsIDocShell : nsIDocShellTreeItem
const long INTERNAL_LOAD_FLAGS_IS_SRCDOC = 0x40;
const long INTERNAL_LOAD_FLAGS_FIXUP_SCHEME_TYPOS = 0x80;
const long INTERNAL_LOAD_FLAGS_NO_OPENER = 0x100;
/**
* Loads the given URI. This method is identical to loadURI(...) except

View File

@ -0,0 +1,20 @@
function handleRequest(request, response) {
response.setHeader("Content-Type", "text/html");
response.setHeader("Cache-Control", "no-cache");
response.write("<body onload='");
if (!request.hasHeader('Referer')) {
response.write("window.parent.onloadCount++;");
}
if (request.queryString == "newwindow") {
response.write("if (window.opener) { window.opener.parent.onloadCount++; window.opener.parent.doNextStep(); }");
response.write("if (!window.opener) window.close();");
response.write("'>");
} else {
response.write("window.parent.doNextStep();'>");
}
response.write(request.method + " " + Date.now());
response.write("</body>");
}

View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<body onload="window.parent.onloadCount++">
<a href="bug530396-noref.sjs" rel="noreferrer" id="target1">bug530396-noref.sjs</a>
<a href="bug530396-noref.sjs?newwindow" rel="noreferrer" id="target2" target="newwindow">bug530396-noref.sjs with new window</a>
</body>
</html>

View File

@ -60,6 +60,8 @@ support-files = file_bug511449.html
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_bug529119-2.html]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(debug-only failure) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
[test_bug530396.html]
support-files = bug530396-noref.sjs bug530396-subframe.html
[test_bug540462.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_bug551225.html]

View File

@ -0,0 +1,56 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=530396
-->
<head>
<title>Test for Bug 530396</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=530396">Mozilla Bug 530396</a>
<p>
<iframe id="testFrame" src="http://mochi.test:8888/tests/docshell/test/bug530396-subframe.html"></iframe>
<pre id="test">
<script class="testbody" type="text/javascript">
// NOTE: If we ever make subframes do bfcache stuff, this test will need to be
// modified accordingly! It assumes that subframes do NOT get bfcached.
var onloadCount = 0;
var step = 0;
var gTestFrame = document.getElementById('testFrame');
SimpleTest.waitForExplicitFinish();
addLoadEvent(doNextStep);
function doNextStep() {
++step;
switch (step) {
case 1:
is(onloadCount, 1, "Loaded initial page");
sendMouseEvent({type: "click"}, "target2", gTestFrame.contentWindow);
window.setTimeout(doNextStep, 1000);
break;
case 2:
is(onloadCount, 1, "opener must be null");
sendMouseEvent({type: "click"}, "target1", gTestFrame.contentWindow);
break;
case 3:
is(onloadCount, 2, "don't send referrer with rel=referrer");
SimpleTest.finish();
break;
}
}
</script>
</pre>
</html>